问题:写一个函数返回参数二进制中1的个数。例如:10的二进制位为00000000 00000000 00000000 00001010 ,其中1的个数有2个。
解法一:10的二进制:1010 5的二进制:0101 2的二进制:0010 1的二进制:0001 0的二进制:0000
value/2 相当于右移一位,当value==0时,跳出循环。当value%2 == 1时,说明最低位为1,不断右移,测试最低位是不是1,是1就count++,知道统计完所有的1。计算机是以补码存储,正数的补码和原码相同,负数的补码是其原码取反+1,统计正数的时候结果正确,由于负数%2 不会有等于1,所有统计负数的时候会出错。
int Count_one_bits(unsigned int value)
{
//有缺陷,负数会出错。
int count = 0;
while(value != 0)
{
if(value % 2 == 1)
count++;
value /= 2;
}
printf("count = %d\n",count);
return count;
}
解法二:例:10的二进制:1010 1的二进制:0001 1010 & 0001 = 0000(说明10的二进制的最低位为0)
0111&0001=0001(最低位为1) ,任何数和1按位与,可以检测该数最低位的bit位是不是1。一个整型有32个比特位,和1按位与再右移,就可以统计出所有的1。以下代码等价于
while(value != 0)
{
if(value & 1 == 1)
count++;
value = value>>1;
}
int Count_one_bits(unsigned int value)
{
int count = 0;
int i = 0;
for(i = 0; i < 32; i++)
{
if(((value>>i)&1) == 1)
count++;
}
printf("count = %d\n",count);
return count;
}
解法三:更高效的一种算法。
int Count_one_bits(unsigned int value)
{
int count = 0;
while(value != 0)
{
count++;
value = value&(value-1);
}
printf("count = %d\n",count);
return count;
}
运行结果:
int main()
{
int value = -1;
Count_one_bits(value);
return 0;
}