Card 07/ 09
Floating-Point Error: Why 0.1 + 0.2 Is Not 0.3
Totals a hundredth of a penny out, only on some orders, and two numbers that print the same.
double and float store numbers as binary fractions, and most decimal fractions, including 0.1, have no exact binary form. The stored value is the nearest one available, so sums drift by tiny amounts and comparisons with == fail.
Your totals are out by a hundredth of a penny, only on some orders, and only after the third or fourth line. The test that checks the total fails with two numbers that print the same. The smallest case:
System.out.println(0.1 + 0.2);
System.out.println(0.1 + 0.2 == 0.3);0.30000000000000004
falsedouble stores a number as a sum of binary fractions: halves, quarters, eighths. One tenth has no exact representation in that system, in the same way one third has none in decimal. Java stores the closest double it has, and the closest one is not 0.1.
The errors are far below anything you would notice on one value. They accumulate across a sum, and they surface the moment two paths through your code add the same amounts in a different order.
Two fixes, and one non-fix. Hold money as a whole number of pence in a long, or hold it in BigDecimal, Java's class for exact decimal numbers, built from a string. Rounding the answer for display is the non-fix: the stored total is still wrong, and the next sum starts from it.
← → move through sections and cards