Checking if a Number is a Power of 2
The classic bit trick: n & (n - 1) == 0. Learn why this works, edge cases, and real-world applications in memory allocation and hash tables.
Detailed Explanation
The Power-of-2 Check
A positive integer is a power of 2 if and only if it has exactly one bit set in its binary representation. The classic one-liner test is:
function isPowerOf2(n) {
return n > 0 && (n & (n - 1)) === 0;
}
Why It Works
A power of 2 in binary is a single 1 followed by zeros:
1 = 00000001
2 = 00000010
4 = 00000100
8 = 00001000
16 = 00010000
Subtracting 1 flips the lowest set bit and all bits below it:
8 = 00001000
8 - 1 = 00000111
ANDing these together always produces zero for powers of 2 because there is no overlap:
00001000
& 00000111
──────────
00000000
For non-powers of 2, at least one higher bit survives:
6 = 00000110
6 - 1 = 00000101
6 & 5 = 00000100 (not zero!)
Edge Cases
n = 0: Returns false. 0 is not a power of 2, and then > 0check handles this.n < 0: Returns false. Negative numbers are not powers of 2.n = 1: Returns true. 2^0 = 1.
Related Trick: Next Power of 2
To round up to the next power of 2:
function nextPowerOf2(n) {
n--;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
return n + 1;
}
This propagates the highest set bit downward, filling all lower bits with 1, then adds 1.
Use Case
Memory allocators like jemalloc and dlmalloc use power-of-2 checks to classify allocation sizes into bins. If a requested size is already a power of 2, it maps directly to a size class. If not, it's rounded up to the next power of 2 for alignment. Hash tables also require power-of-2 sizes so that modulo operations can be replaced with fast AND masks (index = hash & (size - 1)).