Integer Overflow Doesn't Crash Your Code. In a Coding Interview, That's the Problem.

- Safe midpoint formula: use
lo + (hi - lo) / 2, not(lo + hi) / 2; the sum overflows when both values approach 2^31 - 64-bit accumulator: if n × k exceeds 2 × 10^9, declare your sum as
long(Java/C++),int64(Go), ori64(Rust) before the loop - Cast before multiplying:
(long)a * bpromotes the operation first;(long)(a * b)casts an already-overflowed result - INT_MIN trap:
Math.abs(Integer.MIN_VALUE)returnsInteger.MIN_VALUEin Java; promote tolongbefore any negation that might hit the minimum - Language behavior varies: Python never overflows; Java and Go wrap silently; C/C++ signed overflow is undefined behavior at
-O2; Rust debug builds panic, release builds wrap; JavaScript bitwise ops silently clamp to 32 bits
A bug lived in Java's standard library for nine years. It didn't throw an exception. It didn't produce a stack trace. It just quietly returned the wrong array index for inputs larger than a billion elements, like a coworker who breaks the build and then goes to lunch. Joshua Bloch caught it in 2006 and wrote about it on the Google Research Blog. It's the most documented integer overflow coding interview trap in existence. The culprit was one line:
int mid = (low + high) / 2;
When low and high are both near Integer.MAX_VALUE, their sum overflows 32 bits and goes negative. Divide a negative number by two, you get a negative midpoint, you use that as an array index, and you're somewhere you didn't mean to be. The bug had been in nearly every published binary search implementation since the algorithm appeared in textbooks. The silence was the whole problem.
Integer overflow doesn't announce itself in most languages. No panic. No error. Just a corrupted value that propagates through your logic until you get a wrong answer you can't explain. You'll spend 45 minutes in the interview debugging something that doesn't exist.
Overflow bites at four specific places. The mechanism and fix for each.

Programmer humor that hits different when you've been there.
Your 32-Bit Budget Is Smaller Than You Think
A 32-bit signed integer holds values from -2,147,483,648 to 2,147,483,647. That's roughly -2.1 billion to +2.1 billion. A 64-bit signed integer goes up to about 9.2 × 10^18.
The hardware representation is two's complement: add 1 to 2,147,483,647 and you get -2,147,483,648. No exception. The bit pattern wraps around, like a clock that goes from 11:59 to 12:00 and reads the wrong hour. The arithmetic is internally consistent. It just isn't the arithmetic you intended.

The integer range is a ring, not a line. MAX + 1 doesn't error. It just resets.
The danger is intermediate computations. Two values that each fit comfortably in 32 bits can produce a product or sum that doesn't. The value you read from the constraint block is rarely what the computation touches.
Spot 1: The Binary Search Midpoint
The safe version of the midpoint calculation looks like this:
mid = lo + (hi - lo) // 2
The unsafe version is:
mid = (lo + hi) // 2
These produce the same mathematical result. They don't produce the same result in a 32-bit integer type.
hi - lo is always non-negative and at most hi, so it never overflows. lo + hi can exceed 2^31 - 1 if both are close to the maximum, which wraps to a negative midpoint.
In Java, there's also the unsigned right shift:
int mid = (lo + hi) >>> 1;
The >>> operator treats the 32-bit pattern as unsigned before shifting, even if the value overflowed to negative. For a language that runs on 64-bit hardware, this is a clever workaround. Bloch's own recommendation was lo + (hi - lo) / 2 for its portability. Adopt that one as the default.
This matters for any algorithm that uses a midpoint: binary search, merge sort's merge step, finding the center of a range. If you always write the safe form, you eliminate the class of bug.
For more on writing binary search without off-by-one errors, see Binary Search: One Invariant to Rule the Search Space and Your Binary Search Has an Off-by-One Bug. Prove Me Wrong..

Same math. Different fate. The unsafe version hands you a negative array index with a straight face.
Spot 2: Summing Into the Wrong Type
A problem with constraints 1 <= nums[i] <= 10^9 and 1 <= n <= 10^5 has a maximum possible sum of 10^14. A 32-bit integer holds about 2.1 × 10^9. You're four orders of magnitude short.
// Silent overflow for large n and large values int total = 0; for (int x : nums) { total += x; } // Correct: 64-bit accumulator long total = 0L; for (int x : nums) { total += x; }
The signal: if the constraint allows n elements each up to k, and n × k exceeds 2 × 10^9, your accumulator needs to be 64-bit.
This catches prefix sums, range sums, and any problem that accumulates values over a large array. In C++: use long long and initialize to 0LL. In Go: use int64. In Rust: use i64. In Python: don't worry about it (you lucky duck).
The subtle version of this bug is a 32-bit initializer next to 64-bit arithmetic. Java won't promote automatically:
// Overflow happens before the assignment long total = n * (n + 1) / 2; // Safe: force 64-bit before the multiply long total = (long) n * (n + 1) / 2;
Cast before you multiply, not after. (long)(a * b) casts an already-overflowed 32-bit result. (long)a * b promotes the multiplication itself to 64-bit. One extra pair of parentheses. One interview saved.
Spot 3: Products Are Fast to Overflow
Products escalate quickly. Two values each near 2^16 (around 65,000) multiply to something near 2^32. That's exactly where 32-bit overflow starts.
The sieve of Eratosthenes marks composites starting at p * p. For a sieve up to 10^7, p stays well below 46,341 and p * p fits in 32 bits. Scale the sieve to 10^9 and p can reach 31,623, with p * p still fitting. But write the sieve in Java with int arithmetic and a careless p * p for a larger limit overflows. The fix is the same cast pattern: (long) p * p.
The same principle applies to polynomial rolling hashes, where you compute hash = base * hash + char repeatedly. Here you usually want overflow to happen as modular reduction, but you need to know your language's rules. A language that panics on overflow (Rust in debug mode) will break your hashing loop. Take the mod explicitly on each step:
MOD = (1 << 61) - 1 # Mersenne prime hash = (base * hash + ord(c)) % MOD
This keeps intermediate values bounded and is correct in every language.
Spot 4: The INT_MIN Trap
This one is specific to Java and C/C++, and it surprises people.
In Java:
int x = Integer.MIN_VALUE; // -2147483648 int y = -x; // still -2147483648 System.out.println(x == y); // true
Math.abs(Integer.MIN_VALUE) returns Integer.MIN_VALUE. No exception. The absolute value of the most negative 32-bit integer cannot be represented as a positive 32-bit integer. The positive range only reaches 2^31 - 1, not 2^31. There's no slot for it. This is technically correct behavior. It is also how you lose a coding interview in the last five minutes.
This surfaces in problems involving absolute values, absolute differences, and reversing signs. The fix is to handle Integer.MIN_VALUE explicitly before negating, or to promote to long for the computation.
Problems that involve the reverse of an integer (LeetCode 7) often include the note "return 0 if the reversed integer overflows". That's the hint to check bounds before returning the int.
For a checklist of constraint-edge cases worth covering before you code, see Your Code Works. Your Coding Interview Edge Cases Don't..
Silent Wrap, Panic, or Undefined Behavior: Your Language Decides
The same computation can silently corrupt, panic, or do nothing depending on the language. This isn't academic. Your interview language choice has real consequences here.

C/C++ is the one that says "undefined behavior" and means it. The compiler will optimize away your safety checks.
Python. Arbitrary-precision integers throughout. No overflow, ever. The performance cost exists for astronomical values, but interview constraints don't reach it. This is one genuine ergonomic advantage Python has for competitive programming. Use it smugly.
Java. Signed overflow wraps silently in two's complement. No exception. No undefined behavior. Just a wrong value that continues through your logic. Predictable, but quiet. This is the one that killed the binary search.
C and C++. Signed integer overflow is undefined behavior. The standard says so explicitly. The compiler is allowed to assume signed overflow never happens, and modern compilers exploit this. GCC and Clang at -O2 will optimize away safety checks that are only reachable via overflow. The compiler read the spec and decided it was your fault. Unsigned overflow is defined wrapping. The -fwrapv flag opts into defined wrapping for signed types, at a performance cost.
Go. Defined two's complement wrapping for both signed and unsigned types. No undefined behavior like C/C++. Silent wrong answers like Java. At least it's predictable.
Rust. Debug builds panic on integer overflow with a clear message. Release builds wrap. The same code can pass in release and panic in debug, by design. For explicit control across both modes, use .wrapping_add(), .checked_add() (returns Option), .saturating_add(), or .overflowing_add() depending on what semantics you want. Rust wants you to think about this. Rust is right.
JavaScript. All numbers are IEEE 754 doubles. The safe integer range is -(2^53 - 1) to (2^53 - 1). For interview problems with n up to 10^5 and values up to 10^9, you're fine. The trap is bitwise operations: |, &, ^, <<, >> convert operands to 32-bit signed integers before operating. 10 ** 10 | 0 gives a mangled 32-bit value, not 10^10. Brace yourself.
Three Habits to Catch Integer Overflow Before Your Interviewer Does
You don't need to memorize all of this for every problem. Three habits cover most cases.
Use the safe midpoint formula. lo + (hi - lo) / 2, always. Even in Python where it doesn't matter. The habit is worth more than the characters saved.
When n × k exceeds 2 × 10^9, use 64-bit types. This covers sum accumulation, product calculations, and triangle numbers. Check the constraint block before choosing your accumulator type.
Cast before multiplying. (long)a * b, not (long)(a * b). The cast needs to happen before the overflow, not after.
The fourth case is narrower: if you're negating a value that might be Integer.MIN_VALUE in Java, or working near INT_MIN in C++, use long for that computation or add an explicit bound check.
These bugs show up at the edge of the constraint range, not in your test cases with small inputs. Reading the constraint block before writing code is what catches them. A constraint of 1 <= n <= 10^9 signals something different than 1 <= n <= 10^5, and the code for each problem looks different even if the algorithm is the same.
SpaceComplexity runs voice-based mock interviews where the feedback tracks whether you reason through constraints before coding. Explaining why you chose long over int is the kind of signal that moves the needle on your problem-solving score.
Recap
- 32-bit signed max: ~2.1 × 10^9. 64-bit signed max: ~9.2 × 10^18.
- Midpoint formula:
lo + (hi - lo) / 2, not(lo + hi) / 2. - If n × k > 2 × 10^9, use a 64-bit accumulator.
- Cast before multiplying:
(long)a * b, not(long)(a * b). Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUEin Java. Uselongif negation might hit this.- Python: no overflow. C/C++ signed: undefined behavior. Java/Go: silent wrap. Rust debug: panic. Rust release: wrap. JavaScript: safe to 2^53, bitwise ops clamp to 32 bits.
Further Reading
- Extra, Extra: Nearly All Binary Searches and Mergesorts are Broken (Joshua Bloch, Google Research Blog, 2006)
- Integer overflow (Wikipedia)
- Two's complement (Wikipedia)
- Data Types: The Rust Programming Language (official Rust book)
- Integer Overflow in C (GeeksforGeeks)