tags:

views:

8926

answers:

11

Today I needed a simple algorithm for checking if a number is a power of 2.

The algorithm needs to be:

  1. Simple
  2. Correct for any ulong value.

I came up with this simple algorithm:

private bool IsPowerOfTwo(ulong number)
{
    if (number == 0)
        return false;

    for (ulong power = 1; power > 0; power = power << 1)
    {
        // this for loop used shifting for powers of 2, meaning
        // that the value will become 0 after the last shift
        // (from binary 1000...0000 to 0000...0000) then, the for
        // loop will break out

        if (power == number)
            return true;
        if (power > number)
            return false;
    }
    return false;
}

But then I thought, how about checking if log2x is an exactly round number? But when I checked for 2^63+1, Math.Log returned exactly 63 because of rounding. So I checked if 2 to the power 63 is equal to the original number - and it is, because the calculation is done in doubles and not in exact numbers:

private bool IsPowerOfTwo_2(ulong number)
{
    double log = Math.Log(number, 2);
    double pow = Math.Pow(2, Math.Round(log));
    return pow == number;
}

This returned true for the given wrong value: 9223372036854775809.

Does anyone have any suggestion for a better algorithm?

+216  A: 

There's a simple trick for this problem:

bool IsPowerOfTwo(ulong x)
{
    return (x & (x - 1)) == 0;
}

Discovery of how and why this works is left as an exercise for the reader, as well as consideration of an obvious edge case.


Editor's Note

For completeness, zero is not a power of two. If you want to take into account that edge case, here's how:

bool IsPowerOfTwo(ulong x)
{
    return (x != 0) && ((x & (x - 1)) == 0);
}
Greg Hewgill
Nice! So simple and elegant. Why didn't I think of that?
configurator
looks awesome. didn't understand it though :)
Kripp
@Kripp: The number will be of the binary form 1000...000. When you -1 it, it will be of the form 0111...111. Thus, the two number's binary and would result is 000000. This wouldn't happen for non-power-of-twos, since 1010100 for example would become 1010011, resulting in an (continued...)
configurator
... Resulting in a 1010000 after the binary and. The only false positive would be 0, which is why I would use: return (x != 0)
configurator
Kripp, consider (2:1, 10:1) (4:3, 100:11) (8:7, 1000:111) (16:15, 10000:1111) See the pattern?
Thomas L Holaday
Oh, that’s nice!
Gumbo
it relies on twos complement. since that is almost universal now this it not a problem but I mention it for completeness...
ShuggyCoUk
@ShuggyCoUk: two's complement is how negative numbers are represented. Since this is an unsigned integer, representation of negative numbers is not relevant. This technique only relies on binary representation of nonnegative integers.
Greg Hewgill
oops, you're right, that'll teach me not to read the question properly...
ShuggyCoUk
hail the nice code
Ed
@ShuggyCoUk: Where's the problem with relying on two's complement here? The only value I can think of that would misbehave is Int(16/32/64).MinValue, right? So you simply change x != 0 to x > 0 and the answer is correct
configurator
I am amazed that this is accepted and highly rated. This is wrong. It claims that zero is a power of two.
Matt Howells
@Matt: this has already been discussed in the comments.
configurator
Because comments are finicky things (and may be deleted), I've added what is in the comments to the answer as an `Editor's Note`.
George Stocker
@George Stocker: In C/C++ your editors note will be faster for non-powers of two if the x != 0 is placed on the right side instead of the left side. That way, when x is not a power of two, it will not be compared to 0.
SoapBox
@SoapBox: Not necessarily. You are still checking either way. The difference is one over the other.
0A0D
Beautiful. Just beautiful.
Ed Schembor
@SoapBox - what is more common? Zeroes or non-zero numbers which aren't powers of two? This is a question you can't answer without some more context. And it really, _really_ doesn't matter anyway.
configurator
Statistically, zero is less common than the other 4 billion numbers which are not powers of two. So for 4 billion cases you'll be making two comparisons where one would work. It does make a difference, because in C and C++ the right hand side won't even be checked if the left side is false. So you're saving a comparison. It's not a big deal, but it is easy enough to think about when reading and writing code there's no reason not to do it.
SoapBox
+1  A: 

After posting the question I thought of the following solution:

We need to check if exactly one of the binary digits is one. So we simply shift the number right one digit at a time, and return true if it equals 1. If at any point we come by an odd number ((number & 1) == 1), we know the result is false. This proved (using a benchmark) slightly faster than the original method for (large) true values and much faster for false or small values.

private static bool IsPowerOfTwo(ulong number)
{
    while (number != 0)
    {
        if (number == 1)
            return true;

        if ((number & 1) == 1)
            // number is an odd number and not 1 - so it's not a power of two.
            return false;

        number = number >> 1;
    }
    return false;
}


Of course, Greg's solution is much better.

configurator
+39  A: 

Some sites that document and explain this and other bit twiddling hacks are:

And the grandaddy of them, the book "Hacker's Delight" by Henry Warren, Jr.:

As Sean Anderson's page explains, the expression ((x & (x - 1)) == 0)incorrectly indicates that 0 is a power of 2. He suggests to use:

(!(x & (x - 1)) && x)

to correct that problem.

Michael Burr
+6  A: 

I wrote an article about this recently at http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/. It covers bit counting, how to use logarithms correctly, the classic "x && !(x & (x - 1))" check, and others.

Rick Regan
+18  A: 

return (i & -i) == i

Andreas Petersson
any hint why this will or will not work? i checked its correctness in java only, where there are only signed ints/longs. if it is correct, this would be the superior answer. faster+smaller
Andreas Petersson
Michael Carman
If `i` is an unsigned type, twos complement has nothing to do with it. You're merely taking advantage of the properties of modular arithmetic and bitwise and.
R..
A: 
private static bool IsPowerOfTwo(ulong x)
{
    var l = Math.Log(x, 2);
    return (l == Math.Floor(l));
}
Try that for the number 9223372036854775809. Does it work? I'd think not, because of rounding errors.
configurator
@configurator 922337203685477580_9_ doesn't look like a power of 2 to me ;)
Kirschstein
@Kirschstein: that number gave him a false positive.
Erich Mirabal
Kirschstein: It doesn't look like one to me either. It does look like one to the function though...
configurator
+4  A: 
bool IsPowerOfTwo(ulong x)
{
    return x > 0 && (x & (x - 1)) == 0;
}
Matt Howells
A: 

Find if the given number is a power of 2.

#include <math.h>

int main(void)
{
    int n,logval,powval;
    printf("Enter a number to find whether it is s power of 2\n");
    scanf("%d",&n);
    logval=log(n)/log(2);
    powval=pow(2,logval);

    if(powval==n)
        printf("The number is a power of 2");
    else
        printf("The number is not a power of 2");

    getch();
    return 0;
}
udhaya
Or, in C#: return x == Math.Pow(2, Math.Log(x, 2));
configurator
Broken. Suffers from major floating point rounding issues. Use `frexp` rather than nasty `log` stuff if you want to use floating point.
R..
+1  A: 
bool IsPowerOfTwo( ulong number )
{
   if( i == 0 ) return false;
   ulong minus1 = i -1;
   return (i|minus1) == (i^minus1);
}
caspin
configurator
+1  A: 

Here's a simple c++ solution:

bool IsPowerOfTwo( unsigned int i )
{
   return std::bitset<32>(i).count() == 1;
}
caspin
I don't think C# defines std::bitset...
configurator
@configurator You're right! But this is C++...
Beau Martínez
It's also the slowest solution I've seen...
R..
on gcc this compiles down to a single gcc builtin called `__builtin_popcount`. Unfortunately, one family of processors doesn't yet have a single assembly instruction to do this (x86), so instead it's the fastest method for bit counting. On any other architecture this is a single assembly instruction.
caspin
+1  A: 
bool isPow2 = ((x & ~(x-1))==x)? x : 0;
abelenky
Is this `c#`? I guess this is `c++` as `x` is returned as a bool.
Protron
I did write it as C++. To make it C# is trivial: bool isPow2 = ((x
abelenky
This should also work with C99 bool, but it's ugly.
R..