In the previous article, I briefly introduced the bitwise operation and talked about how to operate integer bits, such as setting a position 0, setting 1, turning, and querying whether a position is 1, finally, an application instance of three bitwise operations is provided for these basic bitwise operations.This is the sequent of the previous article.6Complex bit operations, and analysis of bit operations that are hard to understandBecause I don't want to write too much content in one article, I will give the actual application cases of these bit operations in this article later. Even so,This article is still very important. It is the basis for us to use bitwise operations to solve the problem..
Four basic bit operations in the previous article
1. Set the Nth (n starting from 0) bit of expr to 1: expr | = (1 <n );
2. Set the Nth (n starts from 0) bit of expr to 0: expr & = (~ (1 <n ));
3. Determine whether the Nth (n starting from 0) bit of expr is 1: bool B = expr & (1 <n );
4. Flip the nth digit (n starts from 0) of the expr: expr ^ = (1 <n );
This article8Complex bit operations
The following describes the focus of this article: 8 complex bit operations. It is not easy to understand these bit operations. I will describe them using text + diagrams and try to understand them. What needs to be explained is that for the convenience of drawing, I suppose the data is of the char type (only 8 bits). These bits are also applicable to other types of data.
1.Set1Flip0:X & (x-1)
Assuming x = 01110100, then the binary representation of x, x-1, and x & (x-1) is as follows:
X: |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
0 |
X-1: |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
X & (x-1 ): |
0 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
It can be seen that the function of the X-1 is: Flip the rightmost 1, and make the latter 0 to 1, while keeping the other bit unchanged. Then x & (x-1) will flip the rightmost 1 of x to 0.
This bitwise operation was used in the previous article to calculate the number of 1 in the binary. The idea is: Constantly flip the 1 on the right, knowing to flip the number to 0.
2.Continuous propagation to the right1Bit:X | (x-1)
For example, x = 00101000, then the binary representation of x, X-1 and x | (x-1) is as follows:
X: |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
X-1: |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
X | (x-1 ): |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
From the process above, we can see that x | (x-1) makes the 0 on the Right of 1 on the rightmost of x filled by 1,Note that this cannot be understood as: Flip the rightmost continuous0And should be understood as using the rightmost1Fills all0Bit. Maybe you want to ask why, then assumeX = 00101001, ThenX | (x-1)Still equal00101001, It does not set the rightmost two0Flip!
3.Check the number of unsigned charactersXIs it2Integer power:If (x & (x-1) = 0) return true;
From 1 can be seen: x & (x-1) is to flip the rightmost 1 to 0, if the result is turned to 0, it means that the binary representation of the original number x contains only one 1, so it must be an integer power of 2. This is simple and I will not show it. Remember:2Integer powerAnd2Integer power minus1The result of calculation and execution must be 0.
4.Check the number of unsigned charactersXEqual2Integer power minus1:If (x & (x + 1) = 0) return true;
2Integer power minus1After adding 1, it is equal2Integer powerSo we can use the 3 Method to Determine, which is also very simple and no longer illustrated.
5.Returns the continuous1Bit String flip0Bit String, others remain unchanged:(X | (x-1) + 1) & x
For example, x equals 00101100, then
X: |
0 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
X-1: |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
X | (x-1 ): |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
(X | (x-1) + 1 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
(X | (x-1) + 1) & x |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
Learned from 2: x | (x-1) so that 0 on the Right of 1 on the rightmost of x is filled with 1; and (x | (x-1 )) + 1 makes the consecutive 1-Bit String in x and the 0-bit string on the Right of x become 0, and the 0 on the left of the consecutive 1-Bit String is changed to 1, and keep other bits unchanged; (x | (x-1) + 1) & x makes the continuous 1 bits in x and all bits on its right set to 0, the left side of the continuous one-bit string remains unchanged, so the rightmost continuous one-bit string is flipped.
It's very difficult to explain it in words. It's just a matter of this province. I hope you will not be confused.
6.Check for unsigned integersXEqual2The difference between the two integer power:If (x | (x-1) + 1) & x) = 0) = 0) return true;
The power difference between two integers of 2 is 2k-2j. For example, if k is 6 and j is 2, the binary value of 26 is: 00.100000, the binary value of 22 is1-22 binary representation as 00111100, we can see that the characteristics of 2k-2j are:In the binary representationJBit toK-1BITs are1 (Slave0Start count), OtherBitBITs are0.
We can see that bitwise operations are performed onKeep othersBitWhen the bit is not changed1OfBitAll bits are flipped0If the result is equal to 0, the original number must be the power difference between two integers of 2! As a matter of fact, 5 has already introduced(X | (x-1) + 1) & xThe function is to flip the right side of the binary representation of x to 0 consecutive strings, so only need to apply 3 calculations (X | (x-1) + 1) the value of & x, and then determine whether it is equal to 0. To illustrate this problem, I demonstrated this process again, where x equals 00111100.
X: |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
X-1: |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
X | (x-1 ): |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
(X | (x-1) + 1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
(X | (x-1) + 1) & x |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
As shown in the preceding table, since the final calculation result is equal to 0, x is the integer power difference of two. In fact, x = 60 = 26-22.