DEV Community

Adam Sawicki
Adam Sawicki

Posted on • Originally published at asawicki.info on

Operations on power of two numbers

Numbers that are powers of two (i.e. 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 and so on...) are especially important in programming, due to the way computers work - they operate on binary representation. Sometimes there is a need to ensure that certain number is power of two. For example, it might be important for size and alignment of some memory blocks. This property simplifies operations on such quantities - they can be manipulated using bitwise operations instead of arithmetic ones.

In this post I'd like to present efficient algorithms for 3 common operations on power-of-2 numbers, in C++. I do it just to gather them in one place, because they can be easily found in many other places all around the Internet. These operations can be implemented using other algorithms as well. Most obvious implementation would involve a loop over bits, but that would give O(n) time complexity relative to the number of bits in operand type. Following algorithms use clever bit tricks to be more efficient. They have constant or logarithmic time and they don't use any flow control.

1. Check if a number is a power of two. Examples:

IsPow2(0)   == true (!!)
IsPow2(1)   == true
IsPow2(2)   == true
IsPow2(3)   == false
IsPow2(4)   == true
IsPow2(123) == false
IsPow2(128) == true
IsPow2(129) == false
Enter fullscreen mode Exit fullscreen mode

This one I know off the top of my head. The trick here is based on an observation that a number is power of two when its binary representation has exactly one bit set, e.g. 128 = 0b10000000. If you decrement it, all less significant bits become set: 127 = 0b1111111. Bitwise AND checks if these two numbers have no bits set in common.

template <typename T> bool IsPow2(T x)
{
    return (x & (x-1)) == 0;
}
Enter fullscreen mode Exit fullscreen mode

2. Find smallest power of two greater or equal to given number. Examples:

NextPow2(0)   == 0
NextPow2(1)   == 1
NextPow2(2)   == 2
NextPow2(3)   == 4
NextPow2(4)   == 4
NextPow2(123) == 128
NextPow2(128) == 128
NextPow2(129) == 256
Enter fullscreen mode Exit fullscreen mode

This one I had in my library for a long time.

uint32_t NextPow2(uint32_t v)
{
    v--;
    v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8;
    v |= v >> 16;
    v++;
    return v;
}
uint64_t NextPow2(uint64_t v)
{
    v--;
    v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8;
    v |= v >> 16; v |= v >> 32;
    v++;
    return v;
}
Enter fullscreen mode Exit fullscreen mode

3. Find largest power of two less or equal to given number. Examples:

PrevPow2(0)   == 0
PrevPow2(1)   == 1
PrevPow2(2)   == 2
PrevPow2(3)   == 2
PrevPow2(4)   == 4
PrevPow2(123) == 64
PrevPow2(128) == 128
PrevPow2(129) == 128
Enter fullscreen mode Exit fullscreen mode

I needed this one just recently and it took me a while to find it on Google. Finally, I found it in this post on StackOveflow.

uint32_t PrevPow2(uint32_t v)
{
    v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8;
    v |= v >> 16;
    v = v ^ (v >> 1);
    return v;
}
uint64_t PrevPow2(uint64_t v)
{
    v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8;
    v |= v >> 16; v |= v >> 32;
    v = v ^ (v >> 1);
    return v;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (3)

Collapse
 
lexlohr profile image
Alex Lohr

Your isPowerOfTwo-Function can be even more simplified:

template <typename T> bool IsPow2(T x)
{
    return (x & 1) == 0;
}

That's because any positive binary number that is a power of two doesn't have the bit representing '1' set.

Otherwise, thanks for the nice post.

Collapse
 
reg__ profile image
Adam Sawicki

This isn't correct. Your code checks if the number is even - 0, 2, 4, 6, 8, 10, 12, 14, ... That's not the same as power of two, which is 1, 2, 4, 8, 16, 32, 64, ...

Collapse
 
lexlohr profile image
Alex Lohr

Ah, that's true, I missed that.