题目:写一个函数,返回参数二进制中1的个数。
eg: 15——–00000000 00000000 00000000 00001111
思路:
(1)模除
模2 得到最后一位是不是1,如果是1,则count++,
除2去掉最后一位,继续模2,除2 ,直到除2的结果为0。
返回count(1的个数)
(拿到一位,去掉一位,除产生的数为0,则结束)
代码实现:
int count_bit_1(int n)
{
int count=0;
while(n)
{
if(n%2==1)
{
count++;
}
n=n/2;
}
return count;
}
看起来似乎很正确,我们测试了几组数据:
15—-4
14—-3
-1—-0
-1中到底有几个1呢?
整型数据要以二进制补码表示。
-1的原码:10000000 ……00000001,-1的补码:11111111 ……11111111。(32位)
所以-1中有32个1。
上述方法只适合计算正整形数据二进制中1的个数。
思路:一个整数有32位,我们把32位每一位判断是不是1,用一个for循环,循环32次。
将参数的二进制序列右移(左移)【 右移>> 左移<<】
右移:将二进制序列向右移一位,左边补符号位。
左移:将二进制序列向左移一位,右边补0。
然后与(&)上1,判断最后一位是不是1.
代码实现:
int count_bit_1(int n)
{
int count = 0;
int i = 0;
for(i=0;i<32;i++)
{
if((n>>i)&1==1)
{
count++;
}
}
return count;
}
优化:上述代码无论参数有多少个1都循环32次,会有时间上的浪费。
可以做到 “有几个1循环几次”
n=n&(n-1)
每一次计算n的二进制位少了一个1,这个1是这个二进制中最后的一个1,一直与下去,直到为0,与几次,则有几个0.
eg:
4—-0100(只有一个1)
0100&0011=0000(只与一次)
15—-1111(4个1)
1111&1110=1110
1110&1101=1100
1100&1011=1000
1000&0111=0000(与四次)
代码实现:
int count_bit_1(int n)
{
int count=0;
while(n)
{
count++;
n=n&(n-1);
}
return count;
}
我在VS2010编译器
如果有误,希望指出