c - 如何仅使用位运算符实现 Bitcount?

标签 c bit-manipulation

任务是仅使用按位运算符实现位计数逻辑。我让它工作得很好,但我想知道是否有人可以建议一种更优雅的方法。

只允许按位操作。没有“如果”、“为了”等

int x = 4;

printf("%d\n", x & 0x1);
printf("%d\n", (x >> 1) & 0x1);
printf("%d\n", (x >> 2) & 0x1);
printf("%d\n", (x >> 3) & 0x1);

谢谢。

最佳答案

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

unsigned int v; // count bits set in this (32-bit value)
unsigned int c; // store the total here

c = v - ((v >> 1) & 0x55555555);
c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
c = ((c >> 4) + c) & 0x0F0F0F0F;
c = ((c >> 8) + c) & 0x00FF00FF;
c = ((c >> 16) + c) & 0x0000FFFF;

编辑:不可否认,它有点优化,这使得它更难阅读。阅读起来更容易:

c = (v & 0x55555555) + ((v >> 1) & 0x55555555);
c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
c = (c & 0x0F0F0F0F) + ((c >> 4) & 0x0F0F0F0F);
c = (c & 0x00FF00FF) + ((c >> 8) & 0x00FF00FF);
c = (c & 0x0000FFFF) + ((c >> 16)& 0x0000FFFF);

这五个步骤中的每一步,将相邻的位以 1、2、4 等为一组相加。 该方法基于分而治之。

在第一步中,我们将位 0 ​​和 1 相加并将结果放入两位段 0-1,将位 2 和 3 相加并将结果放入两位段 2-3 等...

第二步我们将0-1和2-3两位相加结果放入四位0-3,将4-5和6-7两位相加结果放入四位 4-7 等...

例子:

So if I have number 395 in binary 0000000110001011 (0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1)
After the first step I have:      0000000101000110 (0+0 0+0 0+0 0+1 1+0 0+0 1+0 1+1) = 00 00 00 01 01 00 01 10
In the second step I have:        0000000100010011 ( 00+00   00+01   01+00   01+10 ) = 0000 0001 0001 0011
In the fourth step I have:        0000000100000100 (   0000+0001       0001+0011   ) = 00000001 00000100
In the last step I have:          0000000000000101 (       00000001+00000100       )

等于5,这是正确的结果

关于c - 如何仅使用位运算符实现 Bitcount?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22860215/

相关文章:

c - C中ListNode中的指针

c - 扫描不同类型的变量

c - 如何计算二叉树的平均高度?

c++ - 有效地交织位

c - C 中使用 & 运算符进行位操作

c# - 如何在使用 NLua 运行的脚本中对 .NET 枚举执行按位或运算?

c - C 中的 else...if 语句是否等于 else { if }?

c - Scanf 总是返回 0.000000

将两个 8 位整数合并为一个 16 位整数

c - 整数的位反转,忽略整数大小和字节顺序