22

Just out of curiosity, how can you tell if a number x is a power of two (x = 2^n) without using recursion.

Thanks

Kartik
  • 9,463
  • 9
  • 48
  • 52

9 Answers9

54

One way is to use bitwise AND. If a number $x is a power of two (e.g., 8=1000), it will have no bits in common with its predecessor (7=0111). So you can write:

($x & ($x - 1)) == 0

Note: This will give a false positive for $x == 0.

dan04
  • 87,747
  • 23
  • 163
  • 198
  • 1
    Is there another edge case at the minimum value for an int? – anon Feb 11 '11 at 04:17
  • 1
    @anon - The expression always and only returns non-zero if the initial value has multiple bits set. The minimum value for an int has one bit set, due to the use of twos complement (on most platforms), yet is not a power of 2. So yes, I think you're right. You get (for the 8 bits case) 10000000 & 01111111 == 0, which would be telling the truth if these were unsigned values (128 is a power of 2), but not for signed values (-128 isn't a power of 2). –  Feb 11 '11 at 04:26
10

Subtract 1 from the number, then and it with the original number. If the result is zero, it was a power of two.

if (((n-1) & n) == 0) {
    // power of two!
}

(sorry, my PHP is rusty...)

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
3

If it's a power of 2? Well, one way is to convert it to binary, and verify the presence of only 1 1...:

$bin = decbin($number);
if (preg_match('/^0*10*$/', $bin)) {
    //Even Power Of 2
}
ircmaxell
  • 163,128
  • 34
  • 264
  • 314
2

For completeness, if the number is a float, you can test if it's a power of two by chacking if the mantissa is all zeros:

<?php
$number = 1.2379400392853803e27;
$d = unpack("h*", pack("d", $number)); $d = reset($d);
$isPowerOfTwo = substr($d, 0, 13) == "0000000000000";
var_dump($isPowerOfTwo); // bool(true)

Exercise for the reader: corner cases and big-endian machines.

Artefacto
  • 96,375
  • 17
  • 202
  • 225
1

In a binary equivalent of any decimal number which is a power of two will have only one occurrence of 1 in its binary equivalent.

<?php
    $number = 4096;
    $bin = decbin($number);
    if ($number != 1 && substr_count($bin,1) == 1) {
        echo "Yes";
    } else {
        echo "No";
    }
?>
Stranger
  • 10,332
  • 18
  • 78
  • 115
0

The top answer:

($x & ($x - 1)) == 0

seemed to have issues with larger numbers for me, this works well for larger numbers using the same logic but with GMP:

gmp_strval(gmp_and($x, gmp_sub($x, 1))) == 0
Chris Wheeler
  • 1,623
  • 1
  • 11
  • 18
0

use mod 2 to determine if a number is a power of 2

def is_power_of_2(n):
    if n == 0:
        return False
    while n % 2 == 0:
        n = n / 2
    return n == 1
Golden Lion
  • 3,840
  • 2
  • 26
  • 35
0

I tried to implement the same thing without bitwise operators. Finally, I ended up with

return (fmod(log($x, 2), 1) === 0.00)

(In PHP)

Suresh Hemal
  • 40
  • 1
  • 5
-2
Math.log(x)/Math.log(2) == Math.floor(Math.log(x)/Math.log(2))
Leo
  • 37,640
  • 8
  • 75
  • 100
Brent
  • 15
  • 1
  • 1
    This looks liks a reasonable solution in Java on the first look - **but it isnt!** Never compare floats/doubles with the `==` operator! – SebastianH Apr 02 '14 at 17:49