tags:

views:

986

answers:

7

I need a function like this:

// return true iff 'n' is a power of 2, e.g.
// is_power_of_2(16) => true  is_power_of_2(3) => false
bool is_power_of_2(int n);

Can anyone suggest how I could write this? Can you tell me a good web site where this sort of algorithm can be found?

+30  A: 

A power of two will have just one bit set (for unsigned numbers). Something like

bool powerOfTwo = !(x == 0) && !(x & (x - 1));

Will work fine; one less than a power of two is all 1s in the less significant bits, so must AND to 0 bitwise.

As I was assuming unsigned numbers, the == 0 test (that I originally forgot, sorry) is adequate. You may want a > 0 test if you're using signed integers.

Adam Wright
You're missing a '!' or an '==0'
You're also missing a test for negative value of x.
Rob Wells
Neat, how did you edit it without the 'edited x minutes ago' appearing?
What about when x is 0?
Ant
Seriously, how did you just get 120 rep for a demonstrably wrong answer?
@Mike F: that's the wisdom of the crowd for you.
Steve Jessop
@Mike F: Indeed, it does seem people will vote on answers without checking them. Anyone can make a mistake, I guess - if I make any in the future, feel free to edit them out.
Adam Wright
This is still wrong. Vote my answer up please so I get enough rep to edit it :)
Matt Howells
So where did the "edited x minutes ago" go?
Rob Wells
@Matt Howells, How is it wrong?@spider57, there is an "odd" feature that if you edit something within X minutes of posting it, it appear in the edit log. It's intended for typos, but has t doesn't he annoying side effect of hiding these changes.
Adam Wright
*doesn't appear* in the edit log. Sigh. My form today is not good.
Adam Wright
You're suffering for those points anyway ;)
@Adam cheers. I didn't realise that they had a "typo" filter.@Adam it was wrong for signed ints. But your latest edit fixes that now
Rob Wells
+3  A: 
bool is_power_of_2(int i) {
    if ( i < 0 ) {
        return 0;
    }
    return ! (i & (i-1));
}
Rob Wells
The condition should be <= 0
Steve Jessop
Oh. Yes. Good catch! Thanks (-:
Rob Wells
+18  A: 

Powers of two in binary look like this:

1: 0001
2: 0010
4: 0100
8: 1000

Note that there is always exactly 1 bit set. The only exception is with a signed integer. e.g. An 8-bit signed integer with a value of -128 looks like:

10000000

So after checking that the number is greater than zero, we can use a clever little bit hack to test that one and only one bit is set.

bool is_power_of_2(int n) {
    return x > 0 && !(x & (x−1));
}

For more bit twiddling see here.

Matt Howells
A: 

This isn't the fastest or shortest way, but I think it is very readable. So I would do something like this:

bool is_power_of_2(int n)
  int bitCounter=0;
  while(n) {
    if ((n & 1) == 1) {
      ++bitCounter;
    }
    n >>= 1;
  }
  return (bitCounter == 1);
}

This works since binary is based on powers of two. Any number with only one bit set must be a power of two.

Jere.Jones
It may not be fast or short, but it's correct unlike the top answers.
The top answers are correct.
Larry Gritz
At time of commenting they were all bugged. They have since been edited into an acceptable state.
+27  A: 

"(n & (n - 1)) == 0" is best. However, note that it will incorrectly return true for n=0, so if that is possible, you will want to check for it explicitly.

http://www-graphics.stanford.edu/~seander/bithacks.html has a large collection of clever bit-twiddling algorithms, including this one.

Anonymous
great web site (and answer), thanks
Ant
A: 

Another way to go (maybe not fastest) is to determine if ln(x) / ln(2) is a whole number.

MikeJ
There's no maybe about it :-).
paxdiablo
This would have problems with floating point inaccuracy. ln(1<<29) / ln(2) comes out to 29.000000000000004.
Anonymous
A: 

The very simplest way is to use the modulus operator; please note that it works for negative numbers as well. It's much simpler that bit shift math and it can be used in virtually any language. You asked for simple, here's simple.

bool is_power_of_2(int n)
{
    return (n % 2 == 0);
}

// You can always do it inline to; where x is an int
if (x%2==0) {
    // x is even
}
else {
    // x is odd
}
The Chairman
This code returns multiples of 2
daniel