两个常用高效位运算函数

之前碰到一些类似于数一个数二进制里有多少1和找最高位等等这样的问题,虽然手写起来也不麻烦,但是看到别人的代码里面很优美的直接塞了一个函数就解决了,还是想学习一下的。

1、最低位1的位数

int __builtin_ffs (unsigned int x)
x= 1 1 2 11_2 112时返回1,x= 11 0 2 110_2 1102时返回2,以此类推。
当然塞一个正的int进去也是没有问题的,一般不会用到负数二进制表示。
如果要返回最低那一位的值的话用lowbit(x)=(x)&(-x)更优美一点。

2、1的个数

int __builtin_popcount (unsigned int x)
这个是比较常用的,时间复杂度貌似为 O ( log ⁡ x ) O(\log x) O(logx)级别

除此之外,统计1的个数的常用方法是打表,例如,把 [ ( 00000000 ) 2 , ( 11111111 ) 2 ] , 即 [ 0 , 2 8 − 1 ] [(00000000)_2,(11111111)_2],即[0,2^8-1] [(00000000)2,(11111111)2],[0,281]内的数有多少个1计算出来,存在一个数组count里面,对于任意一个32位无符号整数(unsigned int),将其切分为4段,从高到低表示为 x 1 , x 2 , x 3 , x 4 x_1,x_2,x_3,x_4 x1,x2,x3,x4那么1的个数就是 c o u n t [ x 1 > > 24 ] + c o u n t [ x 2 > > 16 ] + c o u n t [ x 3 > > 8 ] + c o u n t [ x 4 ] count[x_1>>24]+count[x_2>>16]+count[x_3>>8]+count[x_4] count[x1>>24]+count[x2>>16]+count[x3>>8]+count[x4],可以优化不少常数,如果存储空间足够,通常会保存 2 16 − 1 2^{16}-1 2161以内的表。

基本上就够用了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值