Why does 0.1 + 0.2 not equal 0.3?
Because computers store most decimals in binary floating point, and 0.1 has no exact binary representation — exactly as 1/3 has no exact decimal representation.
The mechanism. Binary fractions are sums of 1/2, 1/4, 1/8, 1/16 and so on. Some decimals map cleanly: 0.5 is 1/2, 0.75 is 1/2 + 1/4. But 0.1 requires an infinitely repeating binary expansion, and the standard format (IEEE 754 double precision) has only 53 bits of significand. The value is therefore rounded to the nearest representable number.
So 0.1 is not really 0.1, and neither is 0.2. Adding two slightly-wrong numbers produces a slightly-wrong sum, and in this case it lands on a value that displays as 0.30000000000000004.
This is not a bug, and it is not specific to JavaScript. It affects every language using IEEE 754 — Python, Java, C, Go, Rust, Excel. Languages differ only in how aggressively they round for display, which is why some appear to get it right.
What to do about it:
Never compare floats with ==. Compare against a tolerance — check whether the absolute difference is below a small epsilon appropriate to your magnitudes.
Never use floats for money. This is the most consequential rule. Use integer minor units — store pence or cents as whole numbers — or a decimal type designed for exact base-10 arithmetic (BigDecimal in Java, decimal in Python and C#, dedicated libraries in JavaScript).
Beware accumulation. Summing many floats compounds error; summing in sorted order or using compensated summation reduces it.
Format at the boundary, rounding only when displaying, not during calculation.
Where floats are appropriate: measurements, graphics, scientific computation — anywhere the inputs are approximate anyway and the range matters more than exactness.