The following the magical formula which gives the number of bits set in a number (Hamming weight).
/*Code to Calculate count of set bits in a number*/
int c;
int v = 7;
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
printf(" Number of Bits is %d",c);
/*-----------------------------------*/
from: http://graphics.stanford.edu/~seander/bithacks.html
Can anyone please explain me the rationale behind this?
Set bits in a binary number is represented by 1. Whenever we calculate the binary number of an integer value then it is formed as the combination of 0's and 1's. So, the digit 1 is known as set bit in the terms of the computer.
We can also use bitset::count(), an inbuilt STL in C++ that returns the count of the total number of set bits in an integer.
To count in binary, convert the last 0 in any number to 1 to add 1, and change any digits following the converted 1 back to 0. If all of the digits are already 1s, add a 1 to the beginning of the number and reset all of the other digits to 1.
It's really quite clever code, and is obviously a lot more difficult to understand than a simple naive loop.
For the first line, let's just take a four-bit quantity, and call it abcd
. The code basically does this:
abcd - ((abcd >> 1) & 0101) = abcd - (0abc & 0101) = abcd - 0a0c
So, in each group of two bits, it subtracts the value of the high bit. What does that net us?
11 - 1 -> 10 (two bits set)
10 - 1 -> 01 (one bit set)
01 - 0 -> 01 (one bit set)
00 - 0 -> 00 (zero bits set)
So, that first line sets each consecutive group of two bits to the number of bits contained in the original value -- it counts the bits set in groups of two. Call the resulting four-bit quantity ABCD
.
The next line:
(ABCD & 0011) + ((ABCD>>2) & 0011) = 00CD + (AB & 0011) = 00CD + 00AB
So, it takes the groups of two bits and adds pairs together. Now, each four-bit group contains the number of bits set in the corresponding four bits of the input.
In the next line, v + (v >> 4) & 0xF0F0F0F
(which is parsed as (v + (v >> 4)) & 0xf0f0f0f
) does the same, adding pairs of four-bit groups together so that each eight-bit group (byte) contains the bit-set count of the corresponding input byte. We now have a number like 0x0e0f0g0h
.
Note that multiplying a byte in any position by 0x01010101
will copy that byte up to the most-significant byte (as well as leaving some copies in lower bytes). For example, 0x00000g00 * 0x01010101 = 0x0g0g0g00
. So, by multiplying 0x0e0f0g0h
, we will leave e+f+g+h
in the topmost byte; the >>24
at the end extracts that byte and leaves you with the answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With