Detecting Powers of Two in Java: Bitwise Tricks and Edge Cases
The author shares a workplace frustration about unfair performance metrics, then illustrates how a hidden 1024‑byte boundary bug led to a discussion of the classic “power‑of‑two” problem, providing clear bit‑wise logic, edge‑case handling, and ready‑to‑run Java code for detecting powers of two.
The article begins with a personal anecdote about feeling like a "tool" at work when performance metrics seem unfair, highlighting that effort must be quantified and aligned with clear goals, otherwise one might consider changing teams.
It then shifts to a technical story: a recent production issue was caused by a hard‑coded value of 1024, which is 2^10. The protocol parser split messages at exactly 1024 bytes, corrupting subsequent data and causing devices to hang. This real‑world bug serves as a segue into the classic algorithmic question of determining whether a number is a power of two.
The most efficient test uses bitwise operations: a number n is a power of two if and only if its binary representation contains exactly one '1'. This can be checked with n & (n - 1), which yields zero only for powers of two. The check must be preceded by n > 0 to avoid false positives for zero, negative numbers, and Integer.MIN_VALUE, which appear to have a single set bit in two's‑complement representation but are not positive powers of two.
public class PowerOfTwo {
// Determine if an int is a power of two
public static boolean isPowerOfTwo(int n) {
// n must be positive
return n > 0 && ((n & (n - 1)) == 0);
}
// Long version for larger values
public static boolean isPowerOfTwo(long n) {
return n > 0 && ((n & (n - 1)) == 0);
}
public static void main(String[] args) {
int[] tests = { -8, -1, 0, 1, 2, 3, 4, 5, 16, 31, 64, 1024,
Integer.MIN_VALUE, Integer.MAX_VALUE };
for (int x : tests) {
System.out.printf("n=%d, isPowerOfTwo=%s%n", x, isPowerOfTwo(x));
}
long big = 1L << 40; // test a large long value
System.out.printf("n=%d, isPowerOfTwo(long)=%s%n", big, isPowerOfTwo(big));
}
}Running this program reveals several subtle points: n=1 counts as a power of two (2^0), a case many overlook. n=0 must return false; forgetting the n > 0 guard is a common mistake. Integer.MIN_VALUE also returns false because the positive‑number check prevents a misleading zero result from n & (n - 1).
For those who prefer library helpers, Integer.highestOneBit(n) == n works as well, but the direct bitwise expression is shorter, faster, and less prone to hidden pitfalls in production code.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
