I got the following question in an interview: "Write a C function that round up a number to next power of 2."
I wrote the following answer:
#include <stdio.h>
int next_pwr_of_2(int num)
{
int tmp;
do
{
num++;
tmp=num-1;
}
while (tmp & num != 0);
return num;
}
void main()
{
int num=9;
int next_pwr;
next_pwr=next_pwr_of_2(num);
printf(" %d \n",next_pwr);
}
The question is: why does the program go out of its do-while
loop when getting to the values 11 and 10?
The power of two is written as 2^x and this utility finds "x". It's very useful when you need to figure out how many bits are needed to represent the given number. For example, if your number is from 0 to 7, then all possible ways that it can be represented in binary are 000, 001, 010, 011, 100, 101, 110, 111.
To check if a given number is a power of 2, we can continuously divide the number by 2, on the condition that the given number is even. After the last possible division, if the value of the number is equal to 1, it is a power of 2. Otherwise, it is not.
If (x & (x-1)) is zero then the number is power of 2. For example, let x be 8 ( 1000 in binary); then x-1 = 7 ( 0111 ).
The loop exits because you did not put parentheses around your condition. This should teach you not to put the unnecessary != 0
in your C/C++ conditions.
You can simplify your code quite a bit, though.
First, observe that temp
equals the prior value of num
, so you can change your loop to
int tmp;
do {
tmp = mum++;
} while (tmp & num); // Don't put unnecessary "!= 0"
Second, the interviewer was probably looking to see if you are familiar with this little trick:
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
Unlike your code that may take up to 1,000,000,000 operations to complete, the above always completes after twelve operations (a decrement, an increment, five shifts, and five OR
s).
Precedence my friend, precedence.
while ((tmp & num) != 0);
Will fix it. ( note the parenthesis around the expression tmp & num
)
!=
has higher precedence than &
, so num != 0
is evaluated before tmp & num
.
If you skip the parenthesis, the expression that is evaluated is : tmp & (num != 0)
First time round, tmp = 9 (1001)
and num != 0
is 1 (0001)
so &
evaluates to 1 (true), and the loop continues.
Now at the end of second iteration, we have, tmp = 10 (1010)
. num != 0
is again 0001, so 1010 & 0001
evaluates to 0
, hence the loop breaks.
Here is the table for reference.
The precedence order is quite unusual, as noted here. Happens all the time :).
Of course you don't have to remember any precedence order, which is just to help the compiler in deciding what is done first if the programmer does not make it clear. You can just correctly parenthesize the expression and avoid such situations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With