Why does this work for determining if a number is a power of 2? - bit-manipulation

int isPower2(int x) {
int neg_one = ~0;
return !(neg_one ^ (~x+1));
}
This code works, I have implemented it and it performs perfectly. However, I cannot wrap my head around why. When I do it by hand, it doesn't make any sense to me.
Say we are starting with a 4 bit number, 4:
0100
This is obviously a power of 2. When I follow the algorithm, though, ~x+1 =
1011 + 1 = 1100
XORing this with negative one (1111) gives 0011. !(0011) = 0. Where am I going wrong here? I know this has to be a flaw in the way I am doing this by hand.

To paraphrase Inigo Montoya, "I do not think this does what you think it does".
Let's break it down.
~x + 1
This flips the bits of 'x' and then adds one. This is the same as taking the 2's complement of 'x'. Or, to put it another way, this is the same as '-x'.
neg_one ^ (~x + 1)
Using what we noted in step 1, this simplifies to ...
neg_one ^ (-x)
or more simply ...
-1 ^ (-x)
But wait! XOR'ing something with -1 is the same as flipping the bits. That is ...
~(-x)
~(-x)
This can be simplified even more if we make use of the 2's complement.
~(-x) + 0
= ~(-x) + 1 - 1
= x - 1
If you are looking for an easy way to determine if a number is a power of 2, you can use the following instead for numbers greater than zero. It will return true if it is a power of two.
(x & (x - 1)) == 0

Related

Why does ~n give -(n+1)?

I wanted to test what happens when I write this code. I can not explain the following case:
Input: 5
Output: -6
#include <iostream>
int lastBit(int n){ return ~(n); }
int main() { std::cout << lastBit(5); }
Computers express negative numbers in quite a specific way. Values are always stored as series of bits and there is no way of introducing negative sign, so this has to be solved differently: one of bits plays role of a negative sign.
But this is not all - the system must be designed to handle maths properly (and ideally, the same way as for positive numbers).
So for instance 0 == 0b00000000. If you subtract 1 from 0, you get -1, but from the binary perspective, due to "binary underflow", 0b00000000 - 0b00000001 == 0b11111111, hence 0b11111111 == -1.
If you then subtract 1 from -1, you get 0b11111111 - 0b00000001 == 0b11111110 == -2. But 2 == 0b00000010, which shows, why -2 != ~2 (and the same rule applies to next values).
The very short, but maybe more intuitive answer might be: "-5 != ~5, because there is only one zero binarily (eg. 0 == -0), so there is always one more negative value than positive ones"
Not on all systems but on systems that use complement of two for signed values. By definition there, the binary representation of negative X = -n, where n is a positive integer, is ~n + 1, which allows signed and unsigned addition operations to be same.
Until C++20 result of ~(n) for signed negative n here would be undefined, because it depends on platform and compiler. In C++20 it's required to behave as if complement of two is used.
I found out the following
5 = 0101
Therefore, ~(5) = 1010
The 1 at the most significant bit denotes negativee (-)
010 = 6
Therefore, output is -6
Since this is a 2's complement machine

Using 1's complement to generate a mask that shows the first non-zero bit

I found an interesting property about 1's complement when reading an interview preparation book.
The property says given a number X, we can generate a mask that shows the first set bit (from right to left) using the 1's complement as follows:
X & ~(X - 1) where ~ stands for 1's complement.
For example, if X = 0b0011 then
0b0011 & 0b1101 = 0b0001
I understood that the author is doing the X-1 to flip the first non-zero bit from the right. But I'm curious as to how did he come up with the idea that taking a 1's complement of X-1 and &ing it with X would result into a bit-mask that shows the first non-zero bit in X.
Its my first time posting at StackOverflow, so my apologies if this question doesn't belong here.
First, notice that for any X, X & (~X) = 0 and X & X = X.
Let X = b_n b_(n-1) ... b_k ... b_1, where b_k is the first set bit.
Thus, X is essentially this:
b_n b_(n-1) ... b_(k+1) 1 0 0 ... 0
---- k ----
X-1 is:
b_n b_(n-1) ... b_(k+1) 0 1 1 ... 1
---- k ----
~(X-1) is:
~b_n ~b_(n-1) ... ~b_(k+1) 1 0 0 ... 0
---- k ----
X & ~(X-1) is:
0 0 .................... 0 1 0 0 ... 0
---- k ----
This can actually be proved using some math. Let x be a positive integer. For all x, there exists a binary representation of x. Additionally, for all x there exists a number x - 1 which also has a binary representation. For all x, the bit in the 1s place, will differ from that of x - 1. Let us define ~ as the ones' complement operator. For any binary number b, ~b turns all of the 0s in b into 1s, and all of the 1s in b into 0s. We can then say that ~(x - 1) must then have the same bit in the 1s place as x. Now, this is simple for odd numbers as all odd numbers o have a 1 in the 1s bit, and so must ~(x - 1), and we can stop there. For even numbers this gets a bit trickier. For all even numbers, e, the 1 bit must be empty. As we stated that x (and also e) must be greater than 0, we can also say that for all even numbers, e, there exists some bit such that the value of that bit is 1. We can also say that for e - 1, the 1s bit must be 1 as e - 1 must be odd. Additionally, we can say that the first bit with a value of 1 in e will be 0 in e - 1. Therefore, using the ones' complement of e - 1, that bit in e that must have been 0, will become 1 by the rules of ones' complement. Using the & operator, that will be the common 1 bit between e and ~(e - 1).
This trick is probably better known written as
X & -X
which is by definition (of -) equivalent, and using the following interpretation of - it becomes very simple to understand:
In string notation for a number that isn't zero, -(a10k) = (~a)10k
If you're unfamiliar with the notation, a10k just means "some string of bits 'a' followed by a 1 followed by k zeroes".
This interpretation just says that negation keeps all the trailing zeroes and the lowest 1, but inverts all higher bits. You can see that it does that from the definition of negation as well, for example if you look at ~X + 1, you see that the +1 cancels out the inversion for the trailing zeroes (which become ones which the +1 carries through) and the lowest set bit (which becomes 0 and then the carry through the trailing zeroes is captured by it).
Anyway, using that interpretation of negation, obviously the top part is removed, the lowest set bit is kept, and the trailing zeroes are just going to stay.
In general, the string notation is very helpful when coming up with these tricks. For example if you know that negation looks like that in string notation, this trick is really quite obvious, and so are some related tricks which you can then also find:
x & x - 1 resets the lowest set bit
x | -x keeps the trailing zeroes but sets all higher bits
x ^ -x keeps the trailing zeroes, resets the lowest set bit, but sets all higher bits
.. and more variants.

Operations on bits, getting the bigger value

I'm not familiar with bitwise operations. I have this sequence:
1 0 0 0 0 : 16
---------------
0 1 1 1 1 : 15
---------------
0 1 1 1 0 : 14
---------------
.
.
.
---------------
0 0 0 1 1 : 3
---------------
0 0 0 1 0 : 2
---------------
0 0 0 0 1 : 1
---------------
I want to check first if there is more than one "1". If that's the case, I want to remove the one that has the bigger decimal value, and to finish, getting the bigger remaining. For example 15, there is four "1", I remove the bigger one, the "1" at "8", I got "0 0 1 1 1 : 7", where the bigger "1" is at "4". How can I do this?
Here's the code that does what you want:
unsigned chk_bits(unsigned int x) {
unsigned i;
if (x != 0 && (x & (x-1)) != 0) {
/* More than one '1' bit */
for (i = ~(~0U >> 1); (x & i) == 0; i >>= 1)
; /* Intentionally left blank */
return x & ~i;
}
return x;
}
Note that I assume you're dealing with unsigned numbers. This is usually safer, because right shifting is implementation defined on signed integers, because of sign extension.
The if statement checks if there's more than one bit set in x. x & (x-1) is a known way to get a number that is the same as x with the first '1' least significant bit turned off (for example, if x is 101100100, then x & (x-1) is 101100000. Thus, the if says:
If x is not zero, and if turning off the first bit set to 1 (from LSB to MSB) results in something that is not 0,
then...
Which is equivalent to saying that there's m ore than 1 bit set in x.
Then, we loop through every bit in x, stopping in the first most significant bit that is set. i is initialized to 1000000000000000000000000000, and the loop keeps right shifting it until x & i evaluates to something that is not zero, at which point we found the first most significant bit that is 1. At that point, taking i's complement will yield the mask to turn off this bit in x, since ~i is a number with every bit set to 1 except the only bit that was a 1 (which corresponds to the highest order bit in x). Thus, ANDing this with x gives you what you want.
The code is portable: it does not assume any particular representation, nor does it rely on the fact that unsigned is 32 or 64 bits.
UPDATE: I'm adding a more detailed explanation after reading your comment.
1st step - understanding what x & (x-1) does:
We have to consider two possibilities here:
x ends with a 1 (.......0011001)
x ends with a 0 (.......0011000)
In the first case, it is easy to see that x-1 is just x with the rightmost bit set to 0. For example, 0011001 - 1 = 0011000, so, effectively, x & (x-1) will just be x-1.
In the second case, it might be slightly harder to understand, but if the rightmost bit of x is a 0, then x-1 will be x with every 0 bit switched to a 1 bit, starting on the least significant bits, until a 1 is found, which is turned into a 0.
Let me give you an example, because this can be tricky for someone new to this:
1101011000 - 1 = 11101010111
Why is that? Because the previous number of a binary number ending with a 0 is a binary number filled with one or more 1 bits in the rightmost positions. When we increment it, like 10101111101111 + 1, we have to increment the next "free" position, i.e., the next 0 position, to turn it into a 1, and then all of the 1-bits to the right of that position are turned into 0. This is the way ANY base-n counting works, the only difference is that for base-2 you only have 0's and 1's.
Think about how base-10 counting works. When we run out of digits, the value wraps around and we add a new digit on the left side. What comes after 999? Well, the counting resets again, with a new digit on the left, and the 9's wrap around to 0, and the result is 1000. The same thing happens with binary arithmetic.
Think about the process of counting in binary; we just have 2 bits, 0 and 1:
0 (decimal 0)
1 (decimal 1 - now, we ran out of bits. For the next number, this 1 will be turned into a 0, and we need to add a new bit to the left)
10 (decimal 2)
11 (decimal 3 - the process is going to repeat again - we ran out of bits, so now those 2 bits will be turned into 0 and a new bit to the left must be added)
100 (decimal 4)
101 (decimal 5)
110 (the same process repeats again)
111
...
See how the pattern is exactly as I described?
Remember we are considering the 2nd case, where x ends with a 0. While comparing x-1 with x, rightmost 0's on x are now 1's in x-1, and the rightmost 1 in x is now 0 in x-1. Thus, the only part of x that remains the same is that on the left of the 1 that was turned into a 0.
So, x & (x-1) will be the same as x until the position where the first rightmost 1 bit was. So now we can see that in both cases, x & (x-1) will in fact delete the rightmost 1 bit of x.
2nd step: What exactly is ~0U >> 1?
The letter U stands for unsigned. In C, integer constants are of type int unless you specify it. Appending a U to an integer constant makes it unsigned. I used this because, as I mentioned earlier, it is implementation defined whether right shifting makes sign extension. The unary operator ~ is the complement operator, it grabs a number, and takes its complement: every 0 bit is turned into 1 and every 1 bit is turned into 0. So, ~0 is a number filled with 1's: 11111111111.... Then I shift it right one position, so now we have: 01111111...., and the expression for this is ~0U >> 1. Finally, I take the complement of that, to get 100000...., which in code is ~(~0U >> 1). This is just a portable way to get a number with the leftmost bit set to 1 and every other set to 0.
You can give a look at K&R chapter 2, more specifically, section 2.9. Starting on page 48, bitwise operators are presented. Exercise 2-9 challenges the reader to explain why x & (x-1) works. In case you don't know, K&R is a book describing the C programming language written by Kernighan and Ritchie, the creators of C. The book title is "The C Programming Language", I recommend you to get a copy of the second edition. Every good C programmer learned C from this book.
I want to check first if there is more than one "1".
If a number has a single 1 in its binary representation then it is a number that can be represented in the form 2x. For example,
4 00000100 2^2
32 00010000 2^5
So to check for single one, you can just check for this property.
If log2 (x) is a whole number then it has single 1 in it's binary representation.
You can calculate log2 (x)
log2 (x) = logy (x) / logy (2)
where y can be anything, which for standard log functions is either 10 or e.
Here is a solution
double logBase2 = log(num)/log(2);
if (logBase2 != (int)logBase2) {
int i = 7;
for (;i >0 ; i--) {
if (num & (1 << i)) {
num &= ~(1 << i);
break;
}
}
}

Please explain in detail the logic behind the output of x &(~0 << n)

I have doubt in logic behind x &(~0 <<n).
First of all I could not get the meaning of ~0. When I tried this in Java it showed -1. How
can we represent -1 in binary and differentiate it from the positive numbers?
The most common way (and the way that Java uses) to represent negative numbers, is called Two's Complement. As mentioned in my comment, one way to calculate the negative in this system is -x = ~(x - 1). An other, equivalent way, is -x = ~x + 1.
For example, in 8bit,
00000001 // 1
00000000 // 1 - 1
11111111 // ~(1 - 1) = ~0 = -1
Adding one to 11111111 would wrap to zero - it makes sense to call "the number such that adding one to it result in zero" minus one.
The numbers with the highest bit set are regarded as negative.
The wikipedia article I linked to contains more information.
As for x & (~0 << n), ~0 is just a way to represent "all ones" (which also happens to be -1, which is irrelevant for this use really). For most n, "all ones" shifted left by n is a bunch of ones followed by n zeroes.
In total, that expression clears the lower n bits of x.
At least, for 0 <= n <= 31.
a << n in Java, where a is an int, is equivalent to a << (n & 31).
Every bit of the byte 0 is 0, and every bit of -1 is 1, so the bitwise negation of 0 is -1.
Hence ~0 is -1.
As for the rest of the question: what are you actually asking?

bitwise bitmanipulation puzzle

Hello is have a question for a school assignment i need to :
Read a round number, and with the internal binaire code with bit 0 on the right and bit 7 on the left.
Now i need to change:
bit 0 with bit 7
bit 1 with bit 6
bit 2 with bit 5
bit 3 with bit 4
by example :
if i use hex F703 becomes F7C0
because 03 = 0000 0011 and C0 = 1100 0000
(only the right byte (8 bits) need to be switched.
The lession was about bitmanipulation but i can't find a way to make it correct for al the 16 hexnumbers.
I`am puzzling for a wile now,
i am thinking for using a array for this problem or can someone say that i can be done with only bitwise ^,&,~,<<,>>, opertors ???
Study the following two functions:
bool GetBit(int value, int bit_position)
{
return value & (1 << bit_position);
}
void SetBit(int& value, int bit_position, bool new_bit_value)
{
if (new_bit_value)
value |= (1 << bit_position);
else
value &= ~(1 << bit_position);
}
So now we can read and write arbitrary bits just like an array.
1 << N
gives you:
000...0001000...000
Where the 1 is in the Nth position.
So
1 << 0 == 0000...0000001
1 << 1 == 0000...0000010
1 << 2 == 0000...0000100
1 << 3 == 0000...0001000
...
and so on.
Now what happens if I BINARY AND one of the above numbers with some other number Y?
X = 1 << N
Z = X & Y
What is Z going to look like? Well every bit apart from the Nth is definately going to be 0 isnt it? because those bits are 0 in X.
What will the Nth bit of Z be? It depends on the value of the Nth bit of Y doesn't it? So under what circumstances is Z zero? Precisely when the Nth bit of Y is 0. So by converting Z to a bool we can seperate out the value of the Nth bit of Y. Take another look at the GetBit function above, this is exactly what it is doing.
Now thats reading bits, how do we set a bit? Well if we want to set a bit on we can use BINARY OR with one of the (1 << N) numbers from above:
X = 1 << N
Z = Y | X
What is Z going to be here? Well every bit is going to be the same as Y except the Nth right? And the Nth bit is always going to be 1. So we have set the Nth bit on.
What about setting a bit to zero? What we want to do is take a number like 11111011111 where just the Nth bit is off and then use BINARY AND. To get such a number we just use BINARY NOT:
X = 1 << N // 000010000
W = ~X // 111101111
Z = W & Y
So all the bits in Z apart from the Nth will be copies of Y. The Nth will always be off. So we have effectively set the Nth bit to 0.
Using the above two techniques is how we have implemented SetBit.
So now we can read and write arbitrary bits. Now we can reverse the bits of the number just like it was an array:
int ReverseBits(int input)
{
int output = 0;
for (int i = 0; i < N; i++)
{
bool bit = GetBit(input, i); // read ith bit
SetBit(output, N-i-1, bit); // write (N-i-1)th bit
}
return output;
}
Please make sure you understand all this. Once you have understood this all, please close the page and implement and test them without looking at it.
If you enjoyed this than try some of these:
http://graphics.stanford.edu/~seander/bithacks.html
And/or get this book:
http://www.amazon.com/exec/obidos/ASIN/0201914654/qid%3D1033395248/sr%3D11-1/ref%3Dsr_11_1/104-7035682-9311161
This does one quarter of the job, but I'm not going to give you any more help than that; if you can work out why I said that, then you should be able to fill in the rest of the code.
if ((i ^ (i >> (5 - 2))) & (1 >> 2))
i ^= (1 << 2) | (1 << 5);
Essentially you need to reverse the bit ordering.
We're not going to solve this for you.. but here's a hint:
What if you had a 2-bit value. How would you reverse these bits?
A simple swap would work, right? Think about how to code this swap with operators that are available to you.
Now let's say you had a 4-bit value. How would you reverse these bits?
Could you split it into two 2-bit values, reverse each one, and then swap them? Would that give you the right result? Now code this.
Generalizing that solution to the 8-bit value should be trivial now.
Good luck!