Algorithm
Power of Two
Computational Mathematics
Programming
Computer Science

Algorithm for finding the smallest power of two that's greater or equal to a given value

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Finding the smallest power of two that is greater than or equal to a number appears in allocators, hash table sizing, buffer growth, and graphics pipelines. The logic is short, but edge cases around zero, negative input, and integer overflow can cause subtle bugs. A good implementation balances correctness, performance, and language-specific limits.

Core Sections

1. Clarify the contract before coding

Start by specifying behavior for every input class:

  • For n equal to one, return one.
  • For n greater than one, return the next power of two that is not smaller than n.
  • For n less than one, either return one or reject input, based on your API rules.
  • For values near integer limits, define overflow behavior explicitly.

Without this contract, one call site may treat zero as valid while another treats it as an error. That inconsistency often leads to production-only failures.

2. Bit-length method for readable correctness

In languages with built-in bit utilities, the clearest method uses the bit length of n - 1. This is readable and usually compiles to efficient instructions.

python
1def next_power_of_two(n: int) -> int:
2    if n <= 1:
3        return 1
4    return 1 << (n - 1).bit_length()
5
6
7for value in [0, 1, 2, 3, 4, 5, 31, 32, 33]:
8    print(value, "->", next_power_of_two(value))

Why this works:

  • If n is already a power of two, n - 1 has all lower bits set.
  • The bit length of n - 1 gives the shift count for the same or next power.
  • Shifting one by that count yields the smallest valid power.

This method is easy to audit and is usually the best default.

3. Branchless widening method for low-level control

In systems languages, a widening sequence is a common pattern. It fills all bits below the highest set bit, then adds one.

c
1#include <stdint.h>
2
3uint32_t next_power_of_two_u32(uint32_t n) {
4    if (n <= 1) return 1;
5    n--;
6    n |= n >> 1;
7    n |= n >> 2;
8    n |= n >> 4;
9    n |= n >> 8;
10    n |= n >> 16;
11    return n + 1;
12}

This approach is fast and predictable, but you must use the correct shift widths for each integer size. For sixty-four bit integers, include one more shift by thirty-two.

4. Overflow and sizing strategy

The largest power of two representable in a fixed-width unsigned integer is limited by type width. If input exceeds that limit, n + 1 can wrap and silently return zero in some languages. Decide your failure mode:

  • Return an error code.
  • Throw an exception.
  • Clamp to maximum supported power.

For memory allocation, clamping can hide dangerously large requests, so explicit failure is usually safer. For non-critical heuristics, clamping may be acceptable.

If your service handles untrusted input, validate range before bit operations. Do not rely on implicit overflow semantics to enforce safety.

5. Testing for confidence and portability

Create a compact test suite that covers boundaries and random values. Also verify monotonic behavior, meaning the output never decreases as input increases.

python
1def slow_reference(n: int) -> int:
2    p = 1
3    while p < max(1, n):
4        p *= 2
5    return p
6
7for n in range(0, 1000):
8    assert next_power_of_two(n) == slow_reference(n)

For cross-language systems, add contract tests so all implementations produce the same results. This prevents inconsistencies between backend services and client SDKs.

Common Pitfalls

  • Forgetting to define behavior for zero and negative input.
  • Using signed arithmetic where overflow behavior is undefined or surprising.
  • Omitting width-specific shifts, causing incorrect results on larger integer types.
  • Treating clamping and hard failure as equivalent in allocator-related code.
  • Testing only happy-path values and missing boundary regressions.

Summary

  • A clear input and overflow contract is more important than any micro-optimization.
  • The bit-length method is usually the clearest and safest implementation choice.
  • The widening method is efficient for low-level code when integer width is handled carefully.
  • Overflow handling should match the risk profile of the calling system.
  • Boundary-heavy tests keep behavior stable across languages and platforms.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms