Count the number of 1(MIT hackmem)

MIT Hackmem

 

int bitcount(unsigned int n)
{   
/* works for 32-bit numbers only    */   
/* fix last line for 64-bit numbers */       
register unsigned int tmp;       
tmp = n - ((n >> 1) & 033333333333) - ((n >> 2) & 011111111111);
return ((tmp + (tmp >> 3)) & 030707070707) % 63;
}

首先,可以把 n 看成是8进制的数,即把 n 三位三位的分开,每位是一个bit。
一个三bit的数字可以看成是abc,它的和为4a+2b+c。如果我们将这个数右移一位,即得到ab,其和为2a+b。将原来的n减去右移一位后的n,得到和为2a+b+c。如果我们在把n右移一位,即把原来的n 右移两位的话,我们将得到一个a,然后再用前面减法的结果2a+b+c减去右移两位后的n 的话,得到和为a+b+c,如下面所示:

                   a b c       n1
右移一位       a b      n2
再右移一位       a      n3

n=n1;
n'=n1-n2;
n''=n'-n3
   =n1-n2-n3
   =4a+2b+c -(2a+b) -a
   =a+b+c;

tmp = n - ((n >> 1) & 033333333333) - ((n >> 2) & 011111111111);

即将每三位的和加到末尾上,其余位为0。

然后,程序return了一个值。

return ((tmp + (tmp >> 3)) & 030707070707) % 63;

这里它是将tmp看成是有六bit数组成的32位数,当然这个是从最低有效位算起的,将每六位数的和加到末尾上,然后用63求余(这里用63求余,是因为1000000是64,如果将tmp看成是由六bit数组成的话,高于63就有一个1,所以可以用取余的方法),最后得到共含有的1的个数。

对于64-bit的数而言,我们可以用3倍的八进制数(即3bit位),即1023。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值