简体   繁体   中英

Bitwise - bitCount's formula meaning?

here is the copy of the code from Integer.bitCount(int i)

I understand all the operators but don't understand how those magic numbers can find out the count! can anyone explain that to me? I can see the pattern (1,2,4,8,16 & 0x5,0x3,0x0f).

        public static int bitCount(int i) {
            // HD, Figure 5-2
            i = i - ((i >>> 1) & 0x55555555);
            i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
            i = (i + (i >>> 4)) & 0x0f0f0f0f;
            i = i + (i >>> 8);
            i = i + (i >>> 16);
            return i & 0x3f;
        }

OK, your code is for 32 bit integers, but let's figure out the first step for 16 bit since the alphabet doesn't have 32 letters. Assume the binary form of your input (with byte boundaries indicated by spaces) is

i                  = ABCDEFGH IJKLMNOP
i >>> 1            = 0ABCDEFG HIJKLMNO
(i >>> 1) & 0x5555 = 0A0C0E0G 0I0K0M0O

So the first two bits of the right hand side in the first assignment are (AB - 0A) . Try the combinations:

A  B  AB-0A
0  0  00-00 = 00
1  0  10-01 = 01
0  1  01-00 = 01
1  1  11-01 = 10

So the first two bits of that result give you the count of bits in the first two bits of the input. The same holds for all the other groups of two bits.

Now you do the same thing again. This time we'll consider input in base 4, so two bits form a digit of the notation below, and we can use full 32 bits.

i                      = ABCD EFGH IJKL MNOP
i & 0x33333333         = 0B0D 0F0H 0J0L 0N0P
i >>> 2                = 0ABC DEFG HIJK LMNO
(i >>> 2) & 0x33333333 = 0A0C 0E0G 0I0K 0M0O

So the first four bits of the result are (0A + 0B) = A + B , and the same holds for any other group of four bits. So at that point, every group of four bits contains the bit count of these four bits in the original input.

Using base 16, the next step is

i                            = AB CD EF GH
i >>> 4                      = 0A BC DE FG
i + (i >>> 4)                = A(A+B) (B+C)(C+D) (D+E)(E+F) (F+G)(G+H)
(i + (i >>> 4)) & 0x0f0f0f0f = 0(A+B) 0(C+D) 0(E+F) 0(G+H)

This works because the bit count in each four-bit-group will always be less than four, so adding two such counts can be represented in four bits without overflow. Therefore the addition will not have any overflow from one four-bit base-16 digit to another. At this point, you have each byte containing the bit count for that byte of the input. Other algorithms may contine from there using clever multiplication, but the code you quoted sticks to addition for the next steps as well.

i                           = A B C D
i >>> 8                     = 0 A B C
i2 = i + (i >>> 8)          = A (A+B) (B+C) (C+D)
i2 >>> 16                   = 0 0 A (A+B)
i3 = i2 + (i2 >>> 1         = A (A+B) (A+B+C) (A+B+C+D)
i3 & 0x3f                   = 0 0 0 (A+B+C+D)

Again this makes use of the fact that there is no overflow between digits.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM