liveBook · Manning

Numerical overflow

As explained in 100 Java Mistakes and How to Avoid Them

Floating-point overflow is a computation exceeding the finite representable range of a floating-point type, typically producing infinity.

Numerical overflow occurs when a computation produces a value that does not fit in the fixed number of bits allocated for its numeric type. Computer arithmetic therefore differs from real-number arithmetic: the result depends on the language and type rather than expanding without limit. section 4.2 section 4.0

In Java, ordinary numeric operations overflow silently. Computations use int, long, float, or double; byte, short, and char are widened to int first. Integral overflow discards high-order bits, while floating-point overflow has different behavior and may produce infinity. A plausible-looking result can therefore be wrong long before later code exposes the cause. section 4.2.1

Table 4.1 Step-by-step computation of the (x * x + 1_000_000) / x expression in Java for different values of x. Incorrect results that occur due to numerical overflow are shown in italics.
x
x * x
x * x + 1000000
(x * x + 1000000)/x
Correct result
10,000
100,000,000
101,000,000
10,100
10,100
46,300
2,143,690,000
2,144,690,000
46,321
46,321
46,340
2,147,395,600
–2,146,571,696
–46,322
46,361
46,350
–2,146,644,796
–2,145,644,796
–46,292
46,371
100,000
1,410,065,408
1,411,065,408
14,110
100,010

Trace the expression (x * x + 1_000_000) / x near the int limit: an intermediate multiplication or addition wraps, turning an expected positive result negative. section 4.2.1

Watch for overflow in operations whose intermediate result can exceed the final result:

  • Multiplication can wrap to a value unrelated to the mathematical product, even when a later division would have reduced it. section 4.2.1
  • Addition in an average such as (a + b) / 2 can overflow before division, despite the average itself fitting in int. section 1.3.3 section 1.4
  • Subtraction-based comparisons can overflow and violate the Comparable contract; compare values directly or use Integer.compare(). section 7.11
  • An inclusive loop ending at Integer.MAX_VALUE or Long.MAX_VALUE can become nonterminating when its counter wraps around. section 3.7
  • Offsets, durations, and scaled monetary amounts can outgrow an int as files, elapsed time, transaction volume, or prices scale. section 4.2.3

A small type can become an API failure

A short can hold no value above 32,767. Using it for a protein alignment penalty worked for typical inputs but failed for unusually large proteins; fixing the problem required changing public method signatures from short to int. Type limits embedded in APIs are expensive to reverse after clients depend on them. section 4.11

Prevent overflow by choosing a type for future scale, not merely current samples. Prefer int over short and double over float when reduced range or precision brings little benefit. Isolate numerical algorithms in well-tested methods, ask explicitly whether overflow is possible, and define the required failure behavior. For computations that must reject overflow, checked operations such as Math.addExact and Math.multiplyExact can turn it into an ArithmeticException instead of silently continuing. section 4.16 section 4.2.1

Static analysis can flag recognizable overflow-prone patterns, but a warning may be irrelevant when input bounds make overflow impossible, and analyzers can miss equivalent code written in a different shape. Tests should include boundary values and extreme combinations; property-based testing can help generate cases, but automated testing alone cannot establish that every overflow path is covered. section 1.3.3 section 1.4

How 100 Java Mistakes and How to Avoid Them covers it

How deep it goes
Explains Java integral wraparound with worked arithmetic, then applies it to APIs, comparisons, loops, files, and money without two’s-complement internals.
Examples
Uses a near-limit arithmetic expression, short-based protein alignment, Excel row APIs, subtraction comparators, inclusive loops, and large-file offsets.
What it assumes
Assumes working Java knowledge while defining fixed-width arithmetic and the widening of smaller primitive types to int.
What you can do after
Diagnose/debug with it by recognizing wraparound-prone expressions and selecting safer types, comparisons, bounds, or checked arithmetic.
How it connects
Connects overflow to primitive types, implicit widening, Comparable, Stream API, static analysis, automated testing, and BigDecimal.

Also explained in

Compare how 7 books explain numerical overflow →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Java Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.