Math 按位-位计数的公式含义?

Math 按位-位计数的公式含义?,math,bitwise-operators,bitcount,Math,Bitwise Operators,Bitcount,这是Integer.bitCountint i中的代码副本 我了解所有的运算符,但不明白那些神奇的数字是如何计算出来的!谁能给我解释一下吗?我可以看到模式1,2,4,8,16和0x5,0x3,0x0f 公共静态int位计数i{ //HD,图5-2 i=i-i>>>1&0x5555; i=i&0x33333333+i>>2&0x33333333; i=i+i>>>4&0x0f0f; i=i+i>>>8; i=i+i>>>16; 返回i&0x3f; } 好的,你的代码是32位整数,但是让我们计算16

这是Integer.bitCountint i中的代码副本

我了解所有的运算符,但不明白那些神奇的数字是如何计算出来的!谁能给我解释一下吗?我可以看到模式1,2,4,8,16和0x5,0x3,0x0f

公共静态int位计数i{ //HD,图5-2 i=i-i>>>1&0x5555; i=i&0x33333333+i>>2&0x33333333; i=i+i>>>4&0x0f0f; i=i+i>>>8; i=i+i>>>16; 返回i&0x3f; }
好的,你的代码是32位整数,但是让我们计算16位整数的第一步,因为字母表没有32个字母。假设输入的二进制形式(字节边界由空格表示)为

i=ABCDEFGH IJKLMNOP i>>>1=0ABCDEFG HIJKLMNO i>>>1&0x5555=0A0C0E0G 0I0K0M0O 所以第一次赋值中右边的前两位是AB-0A。尝试以下组合:

A B AB-0A 0 0 00-00 = 00 1 0 10-01 = 01 0 1 01-00 = 01 1 1 11-01 = 10 结果的前两位给出了输入的前两位的位数。这同样适用于所有其他两位组

现在你又做同样的事情了。这一次,我们将考虑在基4中的输入,所以两个比特形成下面的符号的数字,并且我们可以使用完整的32位。

i=ABCD EFGH IJKL MNOP i&0x33333333=0B0D 0F0H 0J0L 0N0P i>>>2=0ABC DEFG HIJK LMNO i>>2&0x33333333=0A0C 0E0G 0I0K 0M0O 因此,结果的前四位是0A+0B=A+B,对于任何其他四位组都是相同的。因此,在这一点上,每一组四位包含原始输入中这四位的位计数

使用base 16,下一步是

i=AB CD EF GH i>>>4=0A BC DE FG i+i>>>4=AA+B+CC+D+EE+F+GG+H i+i>>>4&0x0f0f=0A+b0c+d0e+f0g+H 这是因为每个四位组中的位计数总是小于四,因此添加两个这样的计数可以用四位表示,而不会溢出。因此,加法将不会从一个四位基址16位数字溢出到另一个四位基址16位数字。此时,每个字节都包含该输入字节的位计数。可以使用巧妙的乘法从那里继续,但您引用的代码在接下来的步骤中也坚持加法

i=A B C D i>>>8=0 A B C i2=i+i>>>8=A+B+C+D i2>>>16=0 A A+B i3=i2+i2>>>1=A+B+B+C A+B+C+D i3&0x3f=0 A+B+C+D
这再次利用了数字之间没有溢出的事实。

可能重复的@PaulR你真的读过另一篇文章了吗?它实际上在哪里解释了公式/算法?另外,另一个帖子是用C写的,而且公式也不一样!这怎么可能是重复的呢?答案链接到,解释了这一点和其他并行位计数方法。由于Java和更广泛的基于C的语言家族都共享相同/相似的按位运算符和语法,因此这种语言几乎不相关。还要注意的是,这个问题还有很多重复的地方——很难只挑一个,我可能没有选择最好的。这里还有一个很好的答案:我不想关闭一个看起来像是封闭式问题副本的问题。建议的副本在结尾使用稍微不同的方法,标题也不太有用。我想让我们把这个问题留在这里。请在投票前考虑这一点,而不是重复投票。