Count bits set in parallel(查找32位整形数中置1的个数)
如果要计算一个整形中的位数有多少位被置位,我们的第一想法就是循环查找。现在我们可以参考:http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
unsigned int bits_counter_v4(unsigned int x) { // count bits of each 2-bit chunk x = x - ((x >> 1) & 0x55555555); // count bits of each 4-bit chunk x = (x & 0x33333333) + ((x >> 2) & 0x33333333); // count bits of each 8-bit chunk x = x + (x >> 4); // mask out junk x &= 0xF0F0F0F; // add all four 8-bit chunks return (x * 0x01010101) >> 24; }
利于这个算法,我们只需要12次操作就可以找出int(32)中被置位的个数。接下来我们来分析下这个算法:
1、相邻2位运算得出“1”的个数:
下面是我们希望得到的运算效果:
左边是位数分布(4种分布)|||||右边是个数(0、1、2三种结果)
00b >> unchanged, still 00b 01b >> unchanged, still 01b 10b >> must be converted to 01b 11b >> must be converted to 10b
接下来给出了可以达到以上效果的算法:首先左移一位,把高位的数给了低位,然后0x55555555是掩码,把高位置0,得到了新的2位数,再用原来的数减去刚刚得到新的两位数,得到我们想要的结果:
00b >> shifted: ?0b >> masked: 00b >> subtraction: 00b - 00b >> 00b 01b >> shifted: ?0b >> masked: 00b >> subtraction: 01b - 00b >> 01b 10b >> shifted: ?1b >> masked: 01b >> subtraction: 10b - 01b >> 01b 11b >> shifted: ?1b >> masked: 01b >> subtraction: 11b - 01b >> 10b
2、相邻4位运算得出“1”的个数:
同理,我们提出期望:
00b and 00b >> 0000b 00b and 01b >> 0001b 00b and 10b >> 0010b 01b and 00b >> 0001b 01b and 01b >> 0010b 01b and 10b >> 0011b 10b and 00b >> 0010b 10b and 01b >> 0011b 10b and 10b >> 0100b
算法:x = (x & 0x33333333) + ((x >> 2) & 0x33333333),在这里我们拿1010b举例,验证结果是否为0100b:
1010b ---->>----- 0010b 0011b 0011b ----&---- ----&---- 0010b 0010b -------------+--------------- 0100b
3、相邻8位运算得出“1”的个数:
算法:x = x + (x >> 4);x &= 0x0F0F0F0F;
4、乘以0x01010101
如果A, B, C, D代表8位数,那么32为数可以被(
A, B, C, D
)表示,乘以0x01010101可以使得(
)32>> (A, B, C, D
A+B+C+D, B+C+D, C+D, D
)32
5、我们左移24位取得我们想要的和。