我只需要在二进制运算方面写一个字节汉明权重的表达式(&,^,>>);没有任何循环,只是一个公式。
我知道有很多算法允许计算汉明重量,但所有算法都使用算术运算或循环。
如果我们从http://en.wikipedia.org/wiki/Hamming_weight采用算法,那么第一个和D = B + C可以写成D = B ^ C ^(B& C<<<<<<<<<<<<<更复杂。
有人有提示吗?
更新: 谢谢你的帮助。实际上,我需要以下内容:
int popcount_1(unsigned char in){
unsigned char m1 = 0x55;
unsigned char m2 = 0x33;
unsigned char m4 = 0x0f;
unsigned char B,C = 0;
unsigned char x = in;
x = (x & (x << 1) & (m1 << 1)) | (m1 & (x ^ (x >> 1)));
B = x & m2;
C = (x >> 2) & m2;
x = B ^ C ^ ((B & C) << 1);
B = (x & m4 ) ^ ((x >> 4) & m4);
C = (x & ((x >> 4) & m4)) << 1;
x = B ^ C ^ ((B & C) << 1);
return x;
}
此代码将导致中变量的汉明权重。它不包含任何+, - 或比较指令,它可以在8位微控制器上工作。 然而,它需要比大多数其他解决方案更多的操作。现在,我正在努力简化它。
UPDATE2:另一种基于64位寄存器的解决方案由@Evgeny Kluev提出
答案 0 :(得分:7)
我认为你能做的最好的是O(log n)。这是32位整数的弹出计数的代码(在Go中)。如果需要,将此扩展到64位应该是显而易见的,希望这些评论能够清楚地说明实际情况:
func popCount(n uint32) int {
// each bit in n is a one-bit integer that indicates how many bits are set
// in that bit.
n = ((n & 0xAAAAAAAA) >> 1) + (n & 0x55555555)
// Now every two bits are a two bit integer that indicate how many bits were
// set in those two bits in the original number
n = ((n & 0xCCCCCCCC) >> 2) + (n & 0x33333333)
// Now we're at 4 bits
n = ((n & 0xF0F0F0F0) >> 4) + (n & 0x0F0F0F0F)
// 8 bits
n = ((n & 0xFF00FF00) >> 8) + (n & 0x00FF00FF)
// 16 bits
n = ((n & 0xFFFF0000) >> 16) + (n & 0x0000FFFF)
// kaboom - 32 bits
return int(n)
}
答案 1 :(得分:3)
我不确定这是否是你搜索的内容,但这里只是一个只使用shift和bitwise的公式:
int weight(unsigned char x)
{
return ((0x876543210 >>
(((0x4332322132212110 >> ((x & 0xF) << 2)) & 0xF) << 2)) >>
((0x4332322132212110 >> (((x & 0xF0) >> 2)) & 0xF) << 2))
& 0xf;
}
这里使用移位操作两次作为数组索引的替代(以找到4位汉明权重)。还有一个移位操作使用数组索引来执行加法。