判断一个整数的二进制位中有多少个1

本文介绍了一种高效算法来计算一个整数二进制表示中1的数量。通过不断进行位运算x=x&(x-1),直到x为0,此过程中1的数量即为所求。这种方法的时间复杂度为O(m),适用于64位整数。

循环: x = x & ( x - 1 ); count++; 直到x为0为止。该方法的时间复杂度是O(m)

在此,不妨把x的二进制位表示为
          x=an-1an-2...a0。
按从低位到高位的顺序,不失一般性,假设x的第i位为第一个为1的二进制位,即:ai=1。此时有:
          x       =an-1an-2...ai+1100...0              <1>
         (x-1)  =an-1an-2...ai+1011...1              <2>
很明显,从式1和式2可以得出,在第一次 x & (x-1) 后:
          x=an-1an-2...ai+1000...0
之后重复同样操作,直到x的二进制位中没有1为止
从上面可以看出,每执行过一次 x & (x-1) 后,都会将x的二进制位中为1的最低位的值变为0,并记数加1。
目前而言,一个整数最大64bit,所有三种方法执行起来都可以认为是0(1)。

以下是几种使用 C 语言判断一个整数二进制中 1 的个数的方法: ### 方法一:逐位右移并与 1 进行按位与运算 ```c #include <stdio.h> int main() { int i, x; int count = 0; scanf("%d", &x); for (i = 0; i < 32; i++) { if (((x >> i) & 1) == 1) count++; } printf("%d\n", count); return 0; } ``` 该方法通过循环 32 次(假设整数为 32 位),每次将整数右移 `i` 位,然后与 1 进行按位与运算,如果结果为 1,则说明该位为 1,计数器 `count` 加 1 [^1]。 ### 方法二:逐位左移并判断最高位 ```c #include <stdio.h> unsigned char func(unsigned char para) { int i = 0, num = 0; for (; i < 8; i++) { if (para & 0x80) num++; para <<= 1; } return num; } int main(void) { unsigned char input = 0; printf("请输入小于等于 255 的值:\n"); scanf("%d", &input); printf("输入数据的二进制数中 1 的位数为:%d", func(input)); return 0; } ``` 此方法针对无符号字符型(8 位),通过循环 8 次,每次判断最高位是否为 1,如果是则计数器 `num` 加 1,然后将变量左移一位 [^2]。 ### 方法三:按位左移 1 并与原数按位与 ```c #include <stdio.h> int main() { int n, count; int k = 1; printf("请输入一个十进制数:\n"); scanf("%d", &n); count = 0; while (k) { if (n & k) count++; k <<= 1; } printf("该二进制中含有%d个 1", count); return 0; } ``` 该方法将 1 不断左移,每次与原数进行按位与运算,如果结果不为 0,则说明该位为 1,计数器 `count` 加 1 [^3]。 ### 方法四:使用 `x & (x - 1)` 消除最低位的 1 ```c #include <stdio.h> #include <string.h> #include <stdlib.h> int func(int x) { int n = 0; while (x) { n++; x = x & (x - 1); } return n; } int main(int argc, char **argv) { if (2 != argc) { printf("Param Num Not Two ! \n"); return -1; } int param; param = atoi(argv[1]); int ret; ret = func(param); printf("ret :%d \n", ret); return 0; } ``` 该方法通过 `x & (x - 1)` 操作消除 `x` 二进制表示中最低位的 1,每消除一次,计数器 `n` 加 1,直到 `x` 为 0 [^4]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值