skip to content

Math.abs and ordinary integer arithmetic can silently overflow. How does this happen, and what does Math offer to detect it?

level: seniorimportance: should knowfreq 38%

answer

  1. int is 32-bit: -2^31..2^31-1; overflow wraps silently (two's complement)
  2. abs(Integer.MIN_VALUE) is negative — +2^31 doesn't fit
  3. addExact/subtractExact/multiplyExact/toIntExact throw ArithmeticException
  4. absExact throws instead of returning the negative MIN_VALUE
  5. floorDiv/floorMod round toward -∞ (unlike truncating / and %)

basics

~20 s

Java ints have a fixed range, so a result too big to fit silently wraps around to a wrong (often negative) value. Math.abs(Integer.MIN_VALUE) stays negative for this reason. Math.addExact, multiplyExact, etc. throw an exception instead of wrapping.

solid answer

~50 s

A Java int is 32 bits, ranging from -2^31 to 2^31-1. Arithmetic that exceeds that range doesn't error — it silently wraps using two's-complement, producing a wrong result. The classic case is Math.abs(Integer.MIN_VALUE): the positive of -2^31 is 2^31, which doesn't fit, so abs returns the same negative value. Plain a + b or a * b can overflow the same way. Math provides *exact* variants — addExact, subtractExact, multiplyExact, incrementExact, negateExact, toIntExact — that perform the operation and throw ArithmeticException the moment the true result wouldn't fit. Use them on counters, sizes, IDs, and financial integer math where a silent wrap is a correctness or security bug. There are also floorDiv/floorMod for division that rounds toward negative infinity (unlike Java's truncating / and %). The exact methods cost a branch but turn a silent corruption into a loud, catchable failure.

go deeper

for a junior

Aware that int has a max and can overflow, and that Java has methods like addExact that catch it.

for a middle

Explains two's-complement wraparound, names addExact/multiplyExact/toIntExact, and knows abs(MIN_VALUE) is negative.

for a senior

Chooses exact methods for security/correctness-sensitive arithmetic, knows floorDiv/floorMod semantics, and when BigInteger is the right escalation.

for a principal

Establishes coding standards (exact arithmetic on untrusted/size/financial math), ties silent overflow to a class of security defects, and weighs the negligible branch cost against the bug risk.

## Fixed-width integers and wraparound A Java `int` is stored in **32 bits**, so it can represent only the range **-2,147,483,648 to 2,147,483,647** (that is, -2^31 to 2^31 - 1). A `long` is 64 bits with a correspondingly larger but still finite range. When an arithmetic result is **larger than the maximum** (or smaller than the minimum), Java does **not** throw an error. Instead it **wraps around** using **two's-complement** representation — the bits that don't fit are discarded and the value silently becomes something else, often a negative number. Example: ``` Integer.MAX_VALUE + 1 == Integer.MIN_VALUE // wraps from +2^31-1 to -2^31 ``` This is *silent overflow*: the program keeps running with a corrupted value, which can become a subtle bug or even a security hole (e.g. a size calculation wrapping negative and bypassing a bounds check). ## The `Math.abs(Integer.MIN_VALUE)` trap `Math.abs` is supposed to return the magnitude — a non-negative number. But: - `Integer.MIN_VALUE` is `-2^31`. - Its positive counterpart would be `+2^31`. - The largest positive `int` is only `2^31 - 1`. So `+2^31` does not fit, and `Math.abs(Integer.MIN_VALUE)` returns `Integer.MIN_VALUE` again — a **negative** result from `abs`. The same is true for `Math.abs(Long.MIN_VALUE)`. This is the canonical example that `abs` is not guaranteed non-negative. ## The exact-arithmetic methods To make overflow **loud instead of silent**, `Math` provides *exact* methods that throw `ArithmeticException` when the mathematically correct result wouldn't fit: - `Math.addExact(a, b)` - `Math.subtractExact(a, b)` - `Math.multiplyExact(a, b)` - `Math.incrementExact(a)` / `Math.decrementExact(a)` - `Math.negateExact(a)` - `Math.absExact(a)` *(throws instead of returning the negative MIN_VALUE)* - `Math.toIntExact(long)` — narrows a `long` to an `int`, throwing if it doesn't fit Each has `int` and `long` overloads. Instead of a corrupt value you get an immediate, catchable exception — turning a silent data-integrity bug into a fail-fast error. ```java int sum = Math.addExact(a, b); // throws ArithmeticException if a+b > Integer.MAX_VALUE ``` ## Floor division and modulo A related pair handles a different surprise. Java's `/` and `%` **truncate toward zero**, so `-7 / 2 == -3` and `-7 % 2 == -1`. When you want division/remainder that rounds **toward negative infinity** (often what you want for wrapping indices or time buckets), use `Math.floorDiv(-7, 2) == -4` and `Math.floorMod(-7, 2) == 1`. `floorMod` always returns a result with the **sign of the divisor**, which is handy for non-negative modular indices. ## When to use which - **Performance-critical inner loops where overflow is provably impossible** → plain `+`/`*`. - **Counters, sizes, allocations, IDs, financial integer math, anything user-influenced** → the `*Exact` methods, so a wrap becomes an exception rather than a silent corruption (this is also a security recommendation). - **Wrapping/circular indices or negative-operand modulo** → `floorDiv` / `floorMod`. - **Genuinely unbounded values** → `BigInteger` (arbitrary precision, never overflows). The exact methods add a tiny overflow check (a branch), which is negligible compared to the cost of a silent integer-overflow bug.

  • When would you reach for the *Exact methods over plain + and *?
    Whenever a silent wrap would be a correctness or security bug — counters, sizes, allocations, IDs, money handled as integers, or any value influenced by untrusted input. They convert a silent overflow into a fail-fast ArithmeticException.
  • How do Math.floorMod and the % operator differ for -7 % 2?
    % truncates toward zero, so -7 % 2 is -1. Math.floorMod(-7, 2) rounds toward negative infinity and returns 1 — its result takes the sign of the divisor, which is convenient for non-negative modular indices.

saying these in an interview costs you the question

  • Believing integer overflow throws an exception by default (it silently wraps).
  • Assuming Math.abs is always non-negative (fails for Integer/Long.MIN_VALUE).
  • Thinking % and floorMod behave the same on negative operands.
  • Reaching for the *Exact methods everywhere and ignoring BigInteger when values are truly unbounded.

context