Advertisement

Type 0.1 + 0.2 into almost any programming language and you get 0.30000000000000004. Every developer meets this eventually, usually with alarm, often concluding the language is broken. It is not a bug — it is the predictable result of how computers store fractional numbers, and understanding it prevents real defects in anything that touches money, measurements or comparisons.

The short version: computers store numbers in binary, and just as one-third cannot be written exactly in decimal (0.333...), many everyday decimals cannot be written exactly in binary.

Binary can't hold every decimal

In base ten, we accept that 1/3 has no exact decimal form. In base two, the same problem hits numbers that look perfectly clean to us: 0.1 and 0.2 have no exact binary representation. The computer stores the closest value it can fit in the bits available, which is very slightly off. Add two slightly-off values and the small errors combine into the visible 0.30000000000000004.

This is not sloppiness; it is a fundamental trade-off. Floating-point numbers pack an enormous range into a fixed number of bits by storing an approximation, which is exactly right for scientific and graphical work and exactly wrong for anything that must be penny-perfect.

Advertisement

The two rules that matter

Rule one: never compare floating-point numbers for exact equality. Checking whether 0.1 + 0.2 equals 0.3 will fail. Instead, check whether the difference between them is smaller than a tiny tolerance (an "epsilon"). Code that says "if the result equals exactly X" over floating-point math is a bug waiting for the wrong input.

Rule two: never store money as a floating-point number. Rounding errors that are invisible in a physics simulation become missing cents in an invoice and failed reconciliations in accounting. The fix is to work in the smallest whole unit — store cents as integers — or use a decimal type designed for exact base-ten arithmetic.

Choosing the right tool

Floating-point is the correct choice for the vast domain it was built for: measurements, graphics, machine learning, simulations, anything where a vanishingly small relative error is irrelevant. For those, its speed and range are exactly what you want, and the tiny imprecision never matters.

For exact decimal needs — currency, precise counters, anything a human will audit to the last digit — reach for integers-of-the-smallest-unit or a dedicated decimal/big-decimal type. The mark of an experienced developer is not memorising the binary representation of 0.1, but knowing which number type each job demands and never comparing floats with equals.