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可以使得A, B, C, D 32>> (A+B+C+D, B+C+D, C+D, D32

5、我们左移24位取得我们想要的和。

 

posted @ 2018-04-26 15:41  h_立青人韦  阅读(680)  评论(0编辑  收藏  举报