Powers of 2

/**
* @return true when n is a power of 2 and false otherwise.
*
* Discussion:
*
* A number is a power of two if only a single bit is set to 1. So check if
* the int n only has one bit!
*/


/*
The Algorithm:
- A number that is a power 2 by definition must be able to divide
  by 2 indefinitely to one.
- Alternatively, a power of two must some instance in 
  ```while (pow(2, i++) == num)``` and once it exceeds the
  number it cannot work.
*/


bool solution1(int n)
{
    double n2 = abs(double(n));

    if (n == 0) return false;
    else if (n == 1) return true;

    while (n2 != 1) {
        n2 /= 2;
        if (n2 != int(n2)) 
            return false;
    }
    return true;
}

/*
The Algorithm:
- Lets perform a bit of math: if n is a power of 2
  then we can define that n = 2^k, when k constant
  integer.

  Then:

  log_2(n) = log_2(2^k)
  log_2(n) = k

  return k == integer.
*/

bool solution2(int n)
{
    if (n == 0)
        return false;

    n = abs(n); 
    double k = log2(n);
    return (k == int(k));
}


/*
The Algorithm:
- Another way of looking at the problem is through bit manipulation.
- We know the following:
  8 4 2 1  
  0 0 0 0

- That is, each bit in the number prepresents some power of 2, and some permutation
  of those numbers can produce any kind of number.
- Since the powers of two are sequential (it doesn't skip any other powers of 2), if
  must mean a power of 2 must contain a single bit.
*/
bool solution3(int n)
{
    if (n == 0) return false;
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if (n & 1)
            count++;
        n >>= 1;
        if (count > 1)
            return false;
    }
    return true;
}

/*
The Algorithm:
- The best of the best. If we know that a power
  of two always contain only 1 set bit, which is therefore
  also its msb, then

  1 0 0 0 0 0 = n
  0 1 1 1 1 1 = n - 1

  so any positive number (discluding the 2's complement bit)
  will always be zeroed out if we so n & ( n - 1 ).
*/
bool solution4(int n)
{    
    n = abs(n);
    return (n & (n - 1)) == 0;
}

int main()
{
    // solution 1
    for (int i = 0; i < 10; i++) 
        cout << boolalpha << solution1(i) << ' ';
    cout << endl;

    for (int i = 0; i < 10; i++) 
        cout << boolalpha << solution1(pow(2, i)) << ' ';
    cout << endl << endl;


    // solution 2
    for (int i = 0; i < 10; i++) 
        cout << boolalpha << solution2(i) << ' ';
    cout << endl;

    for (int i = 0; i < 10; i++) 
        cout << boolalpha << solution2(pow(2, i)) << ' ';
    cout << endl << endl;


    // solution 3
    for (int i = 0; i < 10; i++)
        cout << boolalpha << solution3(i) << ' ';
    cout << endl;

    for (int i = 0; i < 10; i++)
        cout << boolalpha << solution3(pow(2, i)) << ' ';
    cout << endl << endl;

    // solution 4
    for (int i = 0; i < 10; i++)
        cout << boolalpha << solution4(i) << ' ';
    cout << endl;

    for (int i = 0; i < 10; i++)
        cout << boolalpha << solution4(pow(2, i)) << ' ';
    cout << endl << endl;

}

Last updated