在二进制表示中,汉明重量是1的数。我遇到网络并找到了O(1)的答案:
v = v - ((v>>1) & 0x55555555);
v = (v & 0x33333333) + ((v>>2) & 0x33333333);
int count = ((v + (v>>4) & 0xF0F0F0F) * 0x1010101) >> 24;
但是我不太了解算法,无法在任何地方找到它的描述。有人可以解释一下,特别是最后一行(哎呀* 0x1010101然后>> 24意味着什么)?
答案 0 :(得分:22)
这是计算比特的分而治之策略的一部分,称为“人口”功能。这种策略的学术性处理可以在Reingold和Nievergelt,1977年找到。
这个想法是首先将这些位成对,然后是4位,然后是8位,依此类推。例如,如果您有位1011
,则第一对10
变为01
,因为有一位而第二对变为10
因为10 = 2
in二进制,11
中有两位。这里的基本事实是:
population(x) = x - (x/2) - (x/4) - (x/8) - (x/16) - ... etc.
您拥有的确切算法是所谓的“HAKMEM”算法的变体(参见Beeler,Gosper和Schroppel,1972)。该算法并行计算4位字段中的1
,然后将这些和转换为8位和。最后一步是通过乘以0x01010101
来添加这4个字节的操作。 0x0F0F0F0F
掩码通过屏蔽非和信息来获得4个字节的总和。例如,假设8-wise字段为10110110
,则有5位等于0101
,因此我们将10110101
。只有最后四位是重要的,所以我们屏蔽了前四位,即:
10110101 & 0x0F = 00000101
你可以在亨利·沃伦的“黑客喜悦”一书中找到关于计算位数的细节的整章。