Why this matters

The bug. Java doubles are IEEE-754 binary floats. Most decimal fractions round-trip with a tiny error, and the error accumulates in arithmetic. The result is a double that prints as 1.0 in some logs and 0.9999999999999999 in others; either way, == against the literal 1.0 fails unpredictably.

The fix. Use an absolute (or relative) tolerance. For consumer-scale percentages, 1e-9 is conservative; the JDK's Math.ulp(total) gives a value-aware bound for hot paths.

For money. Use BigDecimal (or a long count of the smallest unit) when correctness matters. Doubles are fine for physics, telemetry, and approximations — never for ledger entries.

Review heuristic

Money in a float or double is a bug. Equality on a float is a bug. Accumulation in a long-running average without a corrective term is a slow-burning bug. Each one needs a deliberate justification or a type change.

External reference: CWE-682: Incorrect Calculation.