编程之美2.1节中的扩展题第1题:如果变量是32位的Dword,则如何统计该二进制数中1的个数。
对于该题,我原本的想法还是想采用书中解法三,也就是用统计1中个数的算法v&(v-1),该算法时间复杂度为该32二进制数中“1”的个数。
后来,我参见了[1]中的解法,该解法甚妙,复杂度只有若干个位运算,与“1”的数目无关。由于[1]写的比较难懂,所以在这里解释一下他的解法。
解法一:
int Count(unsigned x)
{
x = x - ((x >> 1) & 0x55555555); // 1
x = (x & 0x33333333) + ((x >> 2) & 0x33333333); // 2
x = (x + (x >> 4)) & 0x0F0F0F0F; //3
x = x + (x >> 8); //4
x = x + (x >> 16); //5
return x & 0x0000003F; // 6
}
我们以0000 0000 0000 0000 0000 0000 1011 0101为例
第一行中,x>>1是右移一位,(x>>1) 为 0000 0000 0000 0000 0000 0000 0101 1010
该结果与0101 0101 0101 0101 0101 0101 0101 0101相与,等于 0000 0000 0000 0000 0000 0000 0101 0000
实际上,((x >> 1) & 0x55555555) 该步是想得到原数据x的偶数位的数据。(代码是先右移,再得奇数位,这个等价于:先得偶数位,再右移)
继续阅读