利用位运算求整数的二进制形式中1的个数
问题说明
对于数字7,它的二进制形式是0111(简单起见,这里只显示四位二进制),那么整数7中的1的个数就是3.
思路
这里提出一个基于位运算(与)的方法来求解。首先,我们知道如果N是偶数,那么N-1就是奇数。反之,如果N是奇数,那么N-1就是偶数。如果N为奇数,那么N-1就是把N的最低位(二进制形式)的1置为0。此处插一句,判断一个整数的奇偶性,只要判断其二进制的最低位是1还是0。但如果N为偶数,那么N-1的二进制形式就不单单是把最低位置为0这么简单,要涉及到借位的问题。具体看下面的例子:
数字0 :0000
数字1 :0001
数字2 :0010
数字3 :0011
数字4 :0100
数字5 :0101
数字6 :0110
对于1,3,5而言,得到0,2,4的二进制就是把最低位置为0就行了。恰巧N&(N-1)能做到把最低位的1置为0的效果,其中N为奇数。 对于2,4,6而言,1,3,5的二进制形式就与其差的有点远了。但分别计算N&(N-1)的结果我们就能发现一定的规律,其中N为偶数。N&(N-1)的效果就是把N的从右边数起的第一个1置为0。比如6&5,是0100,把第二位的1置为0了。
总而言之,我们每做一次N&(N-1)运算,就意味着把最低位的1清除了,那么1的个数就加1。第二次运算就把第一次与运算的结果,即N = N&(N-1),再做一次N&(N-1),直到把二进制中的1全部消除为止,也就是N变成全0时,循环停止。
源代码
#include<iostream>
#include<stdio.h>
using namespace std;
int Num_of_One(int num)
{
int count = 0;
while (num != 0)
{
num = num & (num - 1);
count++;
}
return count;
}
int main()
{
//test
printf("%d中有%d个1\n", 0x8f, Num_of_One(0x8f));
printf("%d中有%d个1\n", 0x1f, Num_of_One(0x1f));
return 0;
}