【位操作笔记】位计数算法 使用64位指令计算24位数

位计数

位计数(Counting bits set),指的是计算一个数里bit位置1的个数,例如一个8位数0xea = 0b1110 1010,位置1的个数为5。

算法说明

该算法用于计算最大为24位的数。这个算法需要在支持快速模除的64位CPU上才能达到高性能的效果。计算24位数的位置1的个数,只需要10次操作。

位计数代码

位计数代码

unsigned int count_24bit(unsigned int x)
{
    unsigned int val;

    val =  ((x & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f;
    val += (((x & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) 
         % 0x1f;

    return val;
}

算法来源

Bit Twiddling Hacks

算法计算过程

用abcd efgh ijkl mnop qrst uvwx表示一个24bit数的24个bit位。

一共只需要10次操作。

1.x & 0xfff
x与0xfff, 得到低12bit。
1-1

2.(x & 0xfff) * 0x1001001001001ULL
步骤一得到的数值再乘0x1001001001001ULL。
1-2

3.(x & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL
步骤二得到的数值再与0x84210842108421ULL。
1-3

4.((x & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f
步骤三得到的数值再取模运算0x1f,就是31,31 = 2 5 − 1 2^{5} - 1 251 ,相当于将每5bit的数合并在一起,从0-4,5-9,10-14,15-19,……。
1-4

5.x & 0xfff000
x与0xfff,得到高12bit。
1-5
6.(x & 0xfff000) >> 12
步骤一得到的数值右移12位。
1-6

7.((x & 0xfff000) >> 12) * 0x1001001001001ULL
步骤六得到的数值再乘0x1001001001001ULL。
1-7

8.((x & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL
步骤七得到的数值再与0x84210842108421ULL。
1-8

9.(((x & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f
步骤八得到的数值再取模运算0x1f,就是31,31 = 2 5 − 1 2^{5} - 1 251 ,相当于将每5bit的数合并在一起,从0-4,5-9,10-14,15-19,……。
1-9

10.步骤4和步骤9得到的值相加
val =(x+s+n+u+p+w+r+m+t+o+v+q) + (l+g+b+i+d+k+f+a+h+c+j+e)
最后得到结果,就是把每个bit的值相加,得到的数值就是数里bit位置1的个数。

[参考资料]

Bit Twiddling Hacks By Sean Eron Anderson

[Hacker’s Delight] 作者: Henry S. Warren Jr.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值