关于计算字节位为1的一个问题

   下面代码实现了计算unsignedint X 这个数字中字节为1的个数,

int bit_count(unsigned int x )  
{  
  static unsigned int mask[] = { 0x55555555,  
                                 0x33333333,  
                                 0x0F0F0F0F,  
                                 0x00FF00FF,  
                                 0x0000FFFF };  
  int i;  
  int shift;   /* number of positions to shift to right */  
  
  for( i=0, shift=1; i < 5; i++, shift *= 2 )  
    x = (x & mask[i]) + ( (x >> shift) & mask[i] );  
  return x;  
}  
那么则么去 理解这个问题呢?为什么它可以计算出一个unsigned int 中字节为1的个数

通过自己查阅终于知道了这个是计数器合并问题。

是通过加数据的0位和1位。最终得到的总数就等于在这个数据中1的位数。

其中mask[0]= 0x55555555 = 01010101 01010101 01010101 0101010101间隔)

mask[1]= 0x33333333 = 00110011 00110011 00110011 0011001101间隔2位)

mask[2]= 0x0F0F0F0F = 00001111 00001111 00001111 0000111101间隔4位)

mask[3]= 0x00FF00FF = 00000000 11111111 00000000 1111111101间隔8位)

B[4]= 0x0000FFFF = 00000000 00000000 11111111 11111111 01间隔16位)

      其中把输入数的32Bit(unsigned int)当作32个计数器,代表每一位的1个数。然后合并相邻的2个“计数器”,使i成为16个计数器,每个计数器的值就是这2Bit1的个数;继续合并相邻的2个“计数器“,使i成为8个计数器,每个计数器的值就是4Bit1的个数。。依次类推,直到将i变成一个计数器,那么它的值就是32Biti中值为1Bit的个数。

举例说明,简单来说一个data数据为10110011(二进制),十六进制常量0x55的二进制表示为01010101(有效数据只有8位,前面补0,不考虑)。在这个加法的第一个操作数中,data与这个常量进行了AND运算,奇数的位就被拿出来了。第二操作数((data>> 1) &0x55),首先移动所有的偶数位到奇数位上,然后使用相同的掩码得到这些相同的位。现在,第一个操作数含有data的奇数位而第二个操作数含有偶数位。把这两个操作数相加就相当于把data的奇数位和偶数位相加,这个字节的位被分成了四个2位的字段来展示实际上执行了四个独立的加法。当然,总的位数还没被计算出来。但是,可以使用跟上面一样的技术,经过同样的步骤来计算总数。最终得到一个数字便是字节为1的个数。

这样便可以算出其中为1的个数了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值