今日见到1个函数, 它的作用是求1个整数的二进制数有多少个1.
函数如下:
unsigned long fun(unsigned long x)
{
int count = 0 ;
while(x)
{
count++;
x = x & (x - 1);
}
return count;
}
看了半小时才看懂, 关键是那个 x = x & (x - 1)的意就是把x 化为二进制数后, 把最右边的1变成0.
这样整个函数就很容易明白了。
问题就是 x = x & (x - 1) 为何会把x 的二进制最右边的1变成0呢?
首先& 是1个位运算符, 注意跟逻辑运算符 && 的区别啊。
& 的叫做“位与”, 它的规则就是 如果两个位都是1 则返回1, 否则返回0
也就是说
1 & 1 == 1;
0 & 0 == 0;
1 & 0 == 0;
0 & 1 == 0;
10011101
& 10101000
——————————
10001000
我们把假定 x 的二进制数是A1B, 其中B是n个0(n是任意非负整数)。 而A不受限制
假如 A是1001 B是3个0, 那么 x就是 10011000了
而且A和B中间那个1就是这个二进制数的最右边的1, 因为B是n个0嘛。
那么 x-1 就肯定是 A0C了, C是n个1.
比如 上面的例子 10011000 - 1 == 10010111 所以 C就是3个1了。
所以x & (x -1) 就是
A1B
& A0C
___________
A0B
就如 10011000
& 10010111
————————
10010000
最终A0B 比起A1B就是去掉最右边的1个1啊, 就是这样证明的。