之前碰到一些类似于数一个数二进制里有多少1和找最高位等等这样的问题,虽然手写起来也不麻烦,但是看到别人的代码里面很优美的直接塞了一个函数就解决了,还是想学习一下的。
1、最低位1的位数
int __builtin_ffs (unsigned int x)
x=11211_2112时返回1,x=1102110_21102时返回2,以此类推。
当然塞一个正的int进去也是没有问题的,一般不会用到负数二进制表示。
如果要返回最低那一位的值的话用lowbit(x)=(x)&(-x)更优美一点。
2、1的个数
int __builtin_popcount (unsigned int x)
这个是比较常用的,时间复杂度貌似为O(logx)O(\log x)O(logx)级别
除此之外,统计1的个数的常用方法是打表,例如,把[(00000000)2,(11111111)2],即[0,28−1][(00000000)_2,(11111111)_2],即[0,2^8-1][(00000000)2,(11111111)2],即[0,28−1]内的数有多少个1计算出来,存在一个数组count里面,对于任意一个32位无符号整数(unsigned int),将其切分为4段,从高到低表示为x1,x2,x3,x4x_1,x_2,x_3,x_4x1,x2,x3,x4那么1的个数就是count[x1>>24]+count[x2>>16]+count[x3>>8]+count[x4]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],可以优化不少常数,如果存储空间足够,通常会保存216−12^{16}-1216−1以内的表。
基本上就够用了。
本文介绍了二进制操作中常见的两个技巧:计算一个数的最低位1的位数和统计一个数中1的个数。通过内置函数__builtin_ffs和__builtin_popcount,以及一种打表方法,实现高效计算。
334

被折叠的 条评论
为什么被折叠?



