This post is in continuation with the earlier post, where I have discussed some of the bit manipulation techniques. In previous post, I discussed about how to set, unset and toggle a bit at fixed position like 3rd from right/LSB, 1st from left/MSB etc. Setting and unsetting a bit at fixed position is relatively easier to achieve by using left and right shift operators.
This post will discuss about manipulating a bit at relative positions, like right most 1 bit, left most 0th bit etc. Here also, I will explain all tricks using 8 bit number.
General formula for unsetting the right most 1 bit of a number, X
10000000 (X = -128; in binary)
& 10000000 (-X = -128)
------------
10000000
So adding 1 sets up the right most 0. This can be used to set the right most 0 to 1.
00100100 (X = 36; in binary)
01110111 (X )
This post will discuss about manipulating a bit at relative positions, like right most 1 bit, left most 0th bit etc. Here also, I will explain all tricks using 8 bit number.
Bit Hacks
#1: Unset the rightmost 1 bit
So objective is to turn off the right most 1 bit in a number. If input number is 10100100 then it needs to get converted into a number with b2 (b0 is LSB; highlighted bit is b2) getting turn off.
X = 00100100
X-1 = 00100011
Expected response = 00100000 ??
As shown above, subtracting 1 from number unsets the right most 1 but it also sets the zeros right to 1. Please note that other bits left of targeted 1 remain unchanged. Can X and X-1 be combined to get the expected response. If you notice closely the last 2 bits, ANDing looks to do the job.
00100100 (36 in binary)
& 00100011 (36 -1 )
------------
00100000
& 00100011 (36 -1 )
------------
00100000
10000000 (-128 in binary)
& 01111111 (-128 -1 in binary = 127 )
------------
00000000
00000000 (0 in binary; there is no right most bit)
& 11111111 (0 -1 in binary = -1)
------------
00000000 (no change)
General formula for unsetting the right most 1 bit of a number, X
X = X & (X-1)
Also, be careful of the impact of changing AND to OR in above formula.
#2: Unset all except rightmost 1 bit
So we need to unsets (clears off or changes to 0) all bits except the right most 1 bit. Trivial approach to solve this would be to RIGHT SHIFT the number until you encounter the set bit (i.e. 1) and counting the number of shifts done.
while(X & 1 != 0){
count++;
X = X>> 1;
}
Above approach more easier to think logically but execution complexity and verbosity is high. Let's think of abstracting it into minimal number of steps.
00100100 (X = 36; in binary)
11011011 (~X )
11011011 (~X )
+1
------------
11011100 (-X; in two's complement system -X = ~X+1)
------------
11011100 (-X; in two's complement system -X = ~X+1)
Let's use above -X
00100100 (X = 36; in binary)
& 11011100 (-X)
------------
00000100 (bingo!!!)
& 11011100 (-X)
------------
00000100 (bingo!!!)
10000000 (X = -128; in binary)
& 10000000 (-X = -128)
------------
10000000
And it can be generalized as:
X = X & (~X)#3: Set the right most 0-bit
So this hack expects to turn on the right most 0 bit (irrespective of position). This also can be achieved by multiple steps but we want to achieve it compactly.
00100100 (X = 36; in binary)
+1
------------
00100101 (X+1; )
------------
00100101 (X+1; )
So adding 1 sets up the right most 0. This can be used to set the right most 0 to 1.
00100100 (X = 36; in binary)
| 00100101 (X+1 )
------------
00100101
------------
00100101
| 01111000 (X+1 )
------------
01111111
------------
01111111
So OR-ing X with X+1 does the job.
X = X | (X+1)
Related Post : Bit manipulation in Java
Bit level tricks : setting, unsetting and toggling a bit
----
keep coding !
No comments:
Post a Comment