写一个函数返回参数二进制中1的个数。
方法1:采用模2除2的方法
在这里我们以11为例子
11在内存中的存储是二进制:0000 0000 0000 0000 0000 0000 0000 1011
11%2=1
再将11/2(也可以看成二进制数右移一位)
11/2=5 其二进制:0000 0000 0000 0000 0000 0000 0000 0101
5%2=1
此时再将 5/2(再进行了一次右移动)
得到2 其二进制: 0000 0000 0000 0000 0000 0000 0000 0010
2%2=0
再将2/2(又进行了一次右移动)
得到1 其二进制:0000 0000 0000 0000 0000 0000 0000 0001
1%2=1
再将1/2 得到0 二进制:0000 0000 0000 0000 0000 0000 0000 0000
二进制中再无1,结束判断
可知11的二进制中1的个数有3个
代码如下:
int count_one_bits(unsigned int value){
int count = 0;//用来存储1的个数
while (value > 0){
if (value % 2 == 1){
++count;
value = value / 2;
}
else{
value = value / 2;
}
}
return count;
}
int main(){
int a = 11;
printf("%d\n", count_one_bits(a));
system("pause");
return 0;
}
看到这里,就有小伙伴会很好奇了,负数的二进制又有几个1呢
这里就要提及负数在内存中的存储啦,负数在内存中是以补码的形式存储
以-11为例子
-11: //原码: 1000 0000 0000 0000 0000 0000 0000 1011
//反码: 1111 1111 1111 1111 1111 1111 1111 0100
//补码: 1111 1111 1111 1111 1111 1111 1111 0101
补码为反码+1,要注意的是在这个过程中,最高位为符号位,是不用变化的。
方法2:利用按位与判断,与1按位与,最低位为0,代表原数的最低位为0;最低位为1,代表原数的最低位为1
代码如下
int count_one_bits2(int unsigned value){
int count = 0;
for (int i = 0; i < 32; i++){
//利用按位与判断,与1按位与,最低位为0,代表原数的最低位为0;最低位为1,代表原数的最低位为1
if ((value&1) == 1){
count++;
}
value = value >> 1;//等价于value/=2
}
return count;
}
这里面需要注意的是,运算符的优先级,因为==的运算优先级大于&
方案3(较优解)n&(n-1)
以11 为例子
//11 :0000 0000 0000 0000 0000 0000 0000 1011
//10: 0000 0000 0000 0000 0000 0000 0000 1010
11&10:0000 0000 0000 0000 0000 0000 0000 1010 //10
//9: 0000 0000 0000 0000 0000 0000 0000 1001 //9
10&9: 0000 0000 0000 0000 0000 0000 0000 1000 //8
//7 :0000 0000 0000 0000 0000 0000 0000 0111
8&7: 0000 0000 0000 0000 0000 0000 0000 0000
进行三次的n&(n-1),即为11二进制中1的个数
代码如下
int count_one_bits3(int unsigned value){
int count = 0;
while (value > 0){
value=value&(value - 1);
++count;
}
return count;
}