Here's a bit arithmetic tip that gives you a quick representation of how many 0 at the end of a binary expression of a number. For example, the binary representation of 123 456 is 1 11100010 01000000, so the result of this program is 6.
Here is the code snippet:
unsigned int v; Find the number of trailing zeros in 32-bit V
int R; Result goes here
static const int MULTIPLYDEBRUIJNBITPOSITION[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
R = multiplydebruijnbitposition[((uint32_t) ((V &-V) * 0x077cb531u)) >> 27];
Friends who are familiar with bit arithmetic can recognize that the function of V & V is to take out the right 0 and the first 1. When V = 123 456, V &-V equals 64, which is the binary 1000000. Blame it on, this 0x077cb531 is what is going on? What about array multiplydebruijnbitposition?
This has to start with a nature of the 0x077cb531 itself. This constant is written as a 32-bit binary, you can get the
00000111011111001011010100110001
This 01 string has an incomparable cow B place: If it is seen as a loop, it just contains all 32 possible 5-bit 01 strings, no heavy Complex, and no omission! In fact, such a 01 string is not uncommon, because constructing such a 01 string is exactly equivalent to finding an Euler loop in a graph. For example, construct a graph with 16 vertices named 0000, 0001, 0010, ..., 1111, respectively. If the last 3 bits of a point are exactly equal to the first 3 bits of another point, draw an arrow from the former pointing to the latter. That is, as long as the number on the two vertices satisfies the relationship between ABCD and BCDE (A, B, C, D, E may represent the same number), from ABCD, even a road to BCDE, this road is recorded as ABCDE. Note that some points can be reached between each other (such as 1010 and 0101), and some points even have a path to their own (such as 0000).
The
Constructs a string that contains all possible 5-bit 01 substrings, which is actually equivalent to walking along the arrows in the middle of the process. Assume that the string starts with 0000. If the next number is 1, then 00001 the substring is included, and the latest 4 digits become 0001, but if the next number is 0, then 00000 is included, and the newest 4 is still 0000. From the figure, this is nothing more than a 0000-point departure from the question of which road: you chose to go along 00001 this road to 0001 this point, or along the 00000 road back to 0000 this point. In the same way, every number added is equivalent to a new point along a path, and the 5-digit number written on the road is the 5-digit number that was just taken into account. Our aim is to traverse all paths without repetition and without omission. Obviously each vertex in the graph and the degree of out is 2, so this figure must exist Euler circuit, we can easily construct a meet the requirements of the 01 string. Such 01 strings are called De Bruijn sequences.
What exactly is the De Bruijn sequence here for? Its purpose is simple, which is to provide a unique index for 32 different situations. For example, after 1000000 there are 6 0, 1000000 times 0x077cb531, you get
00000111011111001011010100110001
11011111001011010100110001000000
Equivalent to moving the De Bruijn sequence left 6 bits. Moving this number right 27 bits is equivalent to extracting the first 5 bits of this number:
11011111001011010100110001000000
11011
Because of the nature of the De Bruijn sequence, this 5-digit number is also different when the number at the end of the input number is 0. The array multiplydebruijnbitposition is equivalent to the function of a dictionary. 11011 back to decimal is 27, so we check multiplydebruijnbitposition[27], the program is returned 6.
Note that the program is correct when the number of inputs is at the end of the 0-digit number, because the low-left position is exactly 0 filled.
This part of the God-General code from http://graphics.stanford.edu/~seander/bithacks.html, welcome everyone to the onlookers.
Mysterious constant Comeback! Use 0x077cb531 to calculate the number of the end 0