1-digit count

Source: Internet
Author: User

The so-called one-bit count is to calculate a non-negative integer in binary representation when there are several 1, for example
Decimal 5 = binary 0101,1 bits COUNT = 2
It seems like a very simple algorithm. You just need to traverse every bit in the binary and judge whether it is 1. This is probably the way the code is written.
First Algorithm:
Typedef unsigned int uint;

Int pop (uint x)
{
Int num = 0;
For (int I = 0; I <32; I ++)
{
Num + = (x & (1 <I)> 0;
}
Return num;
}
This algorithm is clear enough. This is the simplest method, but the efficiency is very low. It takes 32 cycles. The complexity of this algorithm is o (n)

The second algorithm:
Int pop (uint x)
{
Int num = 0;
While (x! = 0)
{
Num ++;
X = x & (x-1 );
}
Return num;
}
In fact, this algorithm is also very simple, and also meets our habits of thinking, that is, from the low position to find a bit containing 1, after finding the count and set it to 0, until the end of not finding 1
The num is just a simple count.
X = x & (x-1); sets the rightmost 1 to 0. For more information, see <bit operations>
The complexity of this algorithm depends on the number of 1. If one bit is small, this algorithm is very fast. What if one bit is too large? The following algorithms should be more effective
Int pop (uint x)
{
Int num = 0;
X = ~ X;
While (x! = 0)
{
Num ++;
X = x & (x-1 );
}
Return 32-num;
}
First obtain the inverse of x and then find the number of 1 bits. In fact, we are looking for the number of the original 0 bits. Therefore, the final result is 32-num.
Unfortunately, we cannot assume that the number of 1 bits is large or small, so the complexity of this algorithm is o (n/2)

Third algorithm:
Int pop (uint x)
{
Int num = x;
While (x! = 0)
{
X = x> 1;
Num-= x;
}
Return num;
}
This algorithm is similar to the second algorithm, except that the process of finding 0 is changed to right shift and subtraction.
This algorithm comes from the formula:
Pop (x) = x-Σ (x> I)
In fact, this comes from a more intuitive formula:
Σ 2 ** I = 2 ** (I + 1)-1
That is
1 = 2 ** (I + 1)-Σ 2 ** I
For binary a000..., the number of a bit 1 is a000...
Because it is true for any bit a, the formula with x is used to overlay all the bits.

The number of loops in this algorithm depends on the number of places in the leftmost 1, so the average complexity is o (n/2), and addition operations are not as good

Fourth algorithm:
Int pop (uint x)
{
X = (x & 0x55555555) + (x> 1) & 0x55555555 );
X = (x & 0x33333333) + (x> 2) & 0x33333333 );
X = (x & 0x0f0f0f) + (x> 4) & 0x0f0f0f );
X = (x & 0x00FF00FF) + (x> 8) & 0x00FF00FF );
X = (x & 0x0000FFFF) + (x> 16) & 0x0000FFFF );
Return x;
}
If algorithm 1 is the simplest concept, algorithm 2 and algorithm 3 can be called recursive or recursive, algorithm 4 is the famous idea of divide and conquer.
Review, the general steps of the divide and conquer algorithm are: decomposition, solution, and merge.
Decomposition:
The specific problem is to calculate the 32-bit binary 1 count, which can be divided into 16-bit, 8-bit, 4-bit, 2-bit, and 1-bit binary 1 count.
Solution:
The one-bit binary 1 count is simple.
Merge:
Add two consecutive 1-bit binary 1 counts to a 2-bit binary.
X = (X & 0x55555555) + (x> 1) & 0x55555555); // The 0x55555555 value should be interpreted as 0x01010101010101010101010101010101.
Add two consecutive binary 1 counts to a four-digit binary.
X = (X & 0x33333333) + (x> 2) & 0x33333333); // The 0x33333333 value should be interpreted as 0x00110011001100110011001100110011.
Add two consecutive 4-bit binary 1 counts to an 8-bit binary.
X = (X & 0x0f0f0f) + (x> 4) & 0x0f0f0f); // The 0x0f0f0f should be interpreted as 0x00001111000011110000111100001111.
Add two consecutive 8-bit binary 1 counts to a 16-bit binary.
X = (X & 0x00ff00ff) + (x> 8) & 0x00ff00ff); // The 0x00ff00ff should be interpreted as 0x00000000111111110000000011111111.
Add two consecutive 16-bit binary 1 counts to a 32-bit binary.
X = (X & 0x0000ffff) + (x> 16) & 0x0000ffff); // 0x0000ffff should be interpreted as 0x00000000000000001111111111111111.

In the end, X is the 1 count of 32-bit binary numbers.
The complexity of this algorithm is O (logn). For 32-bit integers, there are only five steps.

Of course, this algorithm can be further optimized. In order to save a few CPU commands, it is irrelevant because it is essentially the same idea.

Fifth algorithm:
Int POP (uint X)
{
Static char table [16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 3, 4 };
Return table [X & 0xf] +
Table [x> 4 & 0xf] +
Table [x> 8 & 0xf] +
Table [x> 12 & 0xf] +
Table [x> 16 & 0xf] +
Table [x> 20 & 0xf] +
Table [x> 24 & 0xf] +
Table [x> 28 & 0xf];
}
The standard lookup method exchanges space for time. This is indeed a very simple and boring algorithm. If we don't care about this space, this algorithm is indeed very effective, in particular, you can open a table to 256 bytes.

Reference <secrets of efficient programs>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.