怎样快速算出一个二进制32位整数中比特位为1的个数?

heidongstar 2004-07-06 10:41:50
如题,我想了半天也不会。
...全文
1025 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
hihihaha 2004-07-11
  • 打赏
  • 举报
回复
代码看不懂是什么意思。。。。
elevation2me 2004-07-11
  • 打赏
  • 举报
回复
《C程序设计语言》的习题2.9


int bitcount (unsigned x )
{
int b;
for (b = 0; x != 0; x &= (x-1))
b++;

return b;
}
lbaby 2004-07-11
  • 打赏
  • 举报
回复
原来value的7,8位如果是00

value = (value & 0x55555555) + ( (value >> 1) & 0x55555555); 之后
value的7,8位就变成了0(0,也就是0个是1的位数)

原来value的7,8位如果是00

value = (value & 0x55555555) + ( (value >> 1) & 0x55555555); 之后
value的7,8位就变成了00(0,也就是0个是1的位数)
lbaby 2004-07-11
  • 打赏
  • 举报
回复 1
size_t bit_cnt(unsigned long value)
{

value = (value & 0x55555555) + ( (value >> 1) & 0x55555555);
value = (value & 0x33333333) + ( (value >> 2) & 0x33333333);
value = (value & 0x0f0f0f0f) + ( (value >> 4) & 0x0f0f0f0f);
value = (value & 0x00ff00ff) + ( (value >> 8) & 0x00ff00ff);
value = (value & 0x0000ffff) + ( (value >> 16) & 0x0000ffff);

return (size_t)value;
}


上边的方法是基于多个位同时参加加法运算的
我们先来看看上边的几个数的二进制模式(如下)

0x55555555:
01010101010101010101010101010101

(value & 0x55555555)
value与0x55555555 相与,奇数位为1的位被保留

( (value >> 1) & 0x55555555)
value右移一位,偶数位为1的位被保留
这样,value的所有位,都保存在
(value & 0x55555555)

( (value >> 1) & 0x55555555)
两个临时结果里了(全在两个临时结果的奇数位上)

二者相加,就得到了局部位数和的信息:
再赋值给value


比如
原来value的最低两位如果是11

value = (value & 0x55555555) + ( (value >> 1) & 0x55555555); 之后
value的最低位就变成了10(2,也就是2个是1的位数)

原来value的3,4位如果是10

value = (value & 0x55555555) + ( (value >> 1) & 0x55555555); 之后
value的3,4位就变成了01(1,也就是1个是1的位数)

原来value的5,6位如果是01

value = (value & 0x55555555) + ( (value >> 1) & 0x55555555); 之后
value的5,6位就变成了1(1,也就是1个是1的位数)

原来value的7,8位如果是00

value = (value & 0x55555555) + ( (value >> 1) & 0x55555555); 之后
value的7,8位就变成了0(0,也就是0个是1的位数)

通过这样的位加法,我们一次就分别计算了1,2;3,4;5,6;...等各位是1的信息
以下的方法,如法炮制:


0x33333333:
00110011001100110011001100110011

计算
1,2,3,4;5,6,7,8;...


0x0f0f0f0f:
00001111000011110000111100001111
...

0x00ff00ff:
00000000111111110000000011111111
...

0x0000ffff:
00000000000000001111111111111111
...


可以自己用一个数试试,马上就可以看到其工作原理了


另外:
上边的代码是基于unsigned long 是32位的假设的
是不可移植的


可以用下边循环:

size_t bit_cnt(unsigned long value)
{
size_t nb=0;
do{
nb += value & 1UL;
value = value >>1;
}while(value);
return nb;
}
gw2004 2004-07-11
  • 打赏
  • 举报
回复
这样可以吗?
int TestNum;
int Sum;
_asm
{
mov eax,TestNum
T1:
test eax,0ffffffffh
jz T2
sal eax,1
jnc T1
inc Sum
jmp T1
}
行吗?
T2:
.......
xjp6688 2004-07-11
  • 打赏
  • 举报
回复
谁能给解释一下?
blueclu0281 2004-07-10
  • 打赏
  • 举报
回复
真的是很高啊
dowhileprogramming 2004-07-10
  • 打赏
  • 举报
回复
我试了一下,是能行。
expert2000 2004-07-06
  • 打赏
  • 举报
回复
代码什么意思?能不能解释一下?
heidongstar 2004-07-06
  • 打赏
  • 举报
回复
zixiaoyu,你太强了,我要的就是这段代码。
zjxiaoyu 2004-07-06
  • 打赏
  • 举报
回复
下面这段神奇的代码可以。
size_t bit_cnt(unsigned long value)
{

value = (value & 0x55555555) + ( (value >> 1) & 0x55555555);
value = (value & 0x33333333) + ( (value >> 2) & 0x33333333);
value = (value & 0x0f0f0f0f) + ( (value >> 4) & 0x0f0f0f0f);
value = (value & 0x00ff00ff) + ( (value >> 8) & 0x00ff00ff);
value = (value & 0x0000ffff) + ( (value >> 16) & 0x0000ffff);

return (size_t)value;
}
BluntBlade 2004-07-06
  • 打赏
  • 举报
回复
用查表可以快上一点点。
archim 2004-07-06
  • 打赏
  • 举报
回复
个人认为没有快速的算法。
有些事情你不得不用看起来最笨的办法去做,而计算机的用途这时侯就体现在可以代替人去做这些看上去很笨的事情。
dowhileprogramming 2004-07-06
  • 打赏
  • 举报
回复
移位比除2和模2快。
dowhileprogramming 2004-07-06
  • 打赏
  • 举报
回复
只有一位位的去测试吧。
heidongstar 2004-07-06
  • 打赏
  • 举报
回复
循环太慢了,有没有不用循环的方法。
archim 2004-07-06
  • 打赏
  • 举报
回复
count = 0;
for(i=0; i<32;i++)
{
if( data & 1)
count++;
data >>= 1;
}
saoyu 2004-07-06
  • 打赏
  • 举报
回复
循环的模2和除2
代码之诗 2004-07-06
  • 打赏
  • 举报
回复
我没有试,如果真能行的话,写出这样一段代码是真TMD的强。

69,381

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧