求32位整数二进制中1的个数

unsigned  long  func(unsigned  long  x)
{
    x 
= (x & 0x55555555UL+ ((x >> 1& 0x55555555UL);
    x 
= (x & 0x33333333UL+ ((x >> 2& 0x33333333UL);
    x 
= (x & 0x0f0f0f0fUL+ ((x >> 4& 0x0f0f0f0fUL);
    x 
= (x & 0x00ff00ffUL+ ((x >> 8& 0x00ff00ffUL);
    x 
= (x & 0x0000ffffUL+ ((x >> 16& 0x0000ffffUL);
    
return x;
}

基本方法是: 2位2位为一组,相加,看看有几个1。再4位4位为一组,相加,看看有几个1......
还是说的不太明白。接着分析。

为了简单说明,先看看8位的情形。相应地,函数里面的语句变成。
x = (x & 0x55) + ((x >> 1) & 0x55);   (1)
x = (x & 0x33) + ((x >> 2) & 0x33);   (2)
x = (x & 0x0f) + ((x >> 4) & 0x0f);   (3)
return x;

假设x=abcdefgh. 0x55=01010101
x & 0x55 = 0b0d0f0h.  (x>>1) & 0x55 = 0a0c0e0g。相加。就可以知道2位2位一组1的个数。

比如x=11111111
x= (x & 0x55) + ((x >> 1) & 0x55); 之后x=10101010。你2位2位地看,10=2, 就是2 2 2 2, 就是说各组都是2个1。
比如x=00101001
x= (x & 0x55) + ((x >> 1) & 0x55); 之后x=00010101。你2位2位地看,就是0 1 1 1, 前1组只有0个1,后面的组都是1个1。

好啦。再来看。0x33=00110011。
x=abcdefgh. 
x=(x & 0x33)+((x >> 2)&0x33); 相当于, 00ab00ef + 00cd00gh。
因为语句(1)之后。ab指示了头两位有多少个1,cd指示了下两位有多少个1。相加00ab+00cd就指示前4位有多少个1。这样就是4位4位为一组。注意这样的分组,组与组之间永远都不会产生进位的。正因为不会产生进位,才可以分开来看。

好啦。下面的过程都是一样的,不再多说。
8位,16位,32位都一样。

还有其他求解方法,比如下面一个:

unsigned  int  func(unsigned  int  x)
{
    unsigned 
int countx = 0;
    
while(x)
    
{
          countx 
++;
          x 
= x & (x-1);
    }

    
return countx;
}
 

每次减1再做或运算就可以干掉从后向前数的第一个1

还有其他经典算法可以在“参考文献”中找到。
转载自:http://blog.chinaunix.net/u/25096/showart_362366.html
参考文献:http://www.everything2.com/index.pl?node_id=1181258 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值