c++ - 数字中设置的位数

标签 c++ c bitmap bit-manipulation bit

下面的神奇公式给出了一个数字中设置的位数(汉明权重)。

/*Code to Calculate count of set bits in a number*/
int c;
int v = 7;
v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
printf(" Number of Bits is %d",c);
/*-----------------------------------*/

来自: http://graphics.stanford.edu/~seander/bithacks.html

谁能解释一下这背后的原理?

最佳答案

这是非常聪明的代码,显然比简单的幼稚循环更难理解。

对于第一行,我们只取一个四位的量,并将其命名为 abcd。代码基本上是这样做的:

abcd - ((abcd >> 1) & 0101) = abcd - (0abc & 0101) = abcd - 0a0c

因此,在每组两位中,它减去高位的值。这对我们有什么好处?

11 - 1 -> 10 (two bits set)
10 - 1 -> 01 (one bit set)
01 - 0 -> 01 (one bit set)
00 - 0 -> 00 (zero bits set)

因此,第一行将每个连续的两位组设置为原始值中包含的位数——它计算两位一组的位。调用得到的四位量ABCD

下一行:

(ABCD & 0011) + ((ABCD>>2) & 0011) = 00CD + (AB & 0011) = 00CD + 00AB

因此,它需要两个位的组并将对相加。现在,每个四位组包含输入的相应四位中设置的位数。

在下一行,v + (v >> 4) & 0xF0F0F0F(解析为 (v + (v >> 4)) & 0xf0f0f0f)做同样的事情,将成对的四位组添加在一起,以便每个八位组(字节)包含相应输入字节的位集计数。我们现在有一个像 0x0e0f0g0h 这样的数字。

请注意,将任何位置的字节乘以 0x01010101 会将该字节复制到最高有效字节(以及在较低字节中保留一些拷贝)。例如,0x00000g00 * 0x01010101 = 0x0g0g0g00。因此,通过乘以 0x0e0f0g0h,我们将 e+f+g+h 留在最高字节;最后的 >>24 提取该字节并留给您答案。

关于c++ - 数字中设置的位数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14555607/

相关文章:

C++ 内部未声明

C 可变长度数组存储时间

android - 仅舍入一个图像角 - 不是全部四个

java - 在位图中定义区域(java)

c++ - Google 测试装置中的变量

c++ - 使用 binomial_heap 和 indirect_cmp

c - 如何修复 mupdf 中的 "cannot find ExtGState dictionary"?

c - 为什么这个递归的 pthread_create 调用会导致数据竞争?

ios - 在 OpenGL ES (iOS) 中绘制二维位图

c++ - 将二维字符串数组传递给函数时出错 (C++)