首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何仅使用位运算符实现Bitcount?

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

Stack Overflow用户
提问于 2010-09-29 00:57:28
回答 4查看 43.4K关注 0票数 15

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

只允许按位操作。没有"if“、"for”等

代码语言:javascript
复制
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);

谢谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-09-29 01:06:48

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

代码语言:javascript
复制
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;

编辑:无可否认,它有一点优化,这使得它更难阅读。它更容易理解为:

代码语言:javascript
复制
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,依此类推。

示例:

代码语言:javascript
复制
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,这是正确的结果

票数 32
EN

Stack Overflow用户

发布于 2010-09-29 03:27:38

我会使用预计算数组

代码语言:javascript
复制
uint8_t set_bits_in_byte_table[ 256 ];

该表中的i-th条目以字节i存储设置位的数量,例如set_bits_in_byte_table[ 100 ] = 3,因为存在以十进制100的二进制表示形式的3个1位(=0x64 = 0110-0100)。

然后我会试着

代码语言:javascript
复制
size_t count_set_bits( uint32_t const x ) {
    size_t count = 0;
    uint8_t const * byte_ptr = (uint8_t const *) &x;
    count += set_bits_in_byte_table[ *byte_ptr++ ];
    count += set_bits_in_byte_table[ *byte_ptr++ ];
    count += set_bits_in_byte_table[ *byte_ptr++ ];
    count += set_bits_in_byte_table[ *byte_ptr++ ];
    return count;
}
票数 3
EN

Stack Overflow用户

发布于 2016-08-26 00:24:47

下面是answer的一个简单示例

代码语言:javascript
复制
a b c d       0 a b c       0 b 0 d    
&             &             +
0 1 0 1       0 1 0 1       0 a 0 c
-------       -------       -------
0 b 0 d       0 a 0 c       a+b c+d

所以我们有2位来存储a+b,2位来存储c+ d,a= 0,1等等,所以我们需要2位来存储它们的和。在下一步中,我们将使用4位来存储2位值的和,等等。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3815165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档