统计一个位数组中非0位的数量,数学上称作:”Hanmming Weight“,汉明重量
SWAR算法计算汉明重量C实现是这样的
// 计算32位二进制的汉明重量
int32_t swar(int32_t i)
{
i = (i & 0x55555555) + ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F);
i = (i * (0x01010101) >> 24);
return i
}
先看上面几个特殊的十六进制数
0x55555555 的二进制为 0101 0101 0101 0101 0101 0101 0101 0101, 奇位为1, 偶数为0
0x33333333 的二进制为 0011 0011 0011 0011 0011 0011 0011 0011
0x0F0F0F0F 的二级制为 0000 1111 0000 1111 0000 1111 0000 1111
0x01010101 的二进制为 0000 0001 0000 0001 0000 0001 0000 0001, 每个字节最后一位是1
1、第一步,(i & 0x55555555) + ((i >> 1) & 0x55555555)
i &0x55555555 得到 j,j 的偶数为全为0,奇数位与 i 的奇数位相对应。
(i >> 1) & 0x55555555 得到 q,q 的偶数位全为0,奇数位与 i 的偶数位相对应。
(i & 0x55555555) + ((i >> 1) & 0x55555555) 即 j + q 得到 z ,z 的第 1 位 和第 2 位的二级制表示(00或01或10)就是 i 的第 1、2 位中值为 1 的数量。这样 z 中每两位一组的二进制表示记录了 i 中对应的两位上的非 0 的个数。
2、第二步,i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
该步中的 i 即上一步中得到的 z ,如果该步骤中得到的结果是 y ,那么 y 中每四位一组的二进制表示记录了 i(最开始的那个数) 中对应的四位上的非 0 的个数。
3、第三步,同上,结果是分成四组,每组8个二进制位来表示。
4、第四步,i = (i * (0x01010101) >> 24)
第三步计算完后,其实已经分成了四组,每组八个二进制位,只要求出每组上二进制表示的值,相加的结果就是汉明重量。
假如 i = 0010 0101 0110 0000 1010 0001 0001 0110来看下是怎么乘的
红框右边的值为有效值,由于 i 的类型是 32 位的 int 型,所以红框内已经是最高位,将其向右移动 24 位,就得到了上面的说的汉明重量(不会超过32)
---------------------
作者:沐雨聼風
来源:CSDN
原文:https://blog.csdn.net/u010320108/article/details/60878085
版权声明:本文为博主原创文章,转载请附上博文链接!