Open any browser console and type 0.1 + 0.2. The answer is 0.30000000000000004. This isn't a bug in JavaScript, and it isn't unique to it: Python, C, Java and almost every other language give the same result, because they all store decimals the same way. The computer isn't being careless. It is being exact about something slightly different from what you asked.

Ten is awkward in binary

In decimal, a third is 0.3333… forever, because 3 doesn't divide evenly into powers of ten. Binary has the same problem with a different victim. Computers count in powers of two, so only fractions whose denominators are powers of two, like ½, ¼ and ⅛, finish neatly. A tenth does not: in binary it is 0.0001100110011001100…, with the block 1001 repeating forever.

A standard double-precision number has only 64 bits to hold everything, so the endless pattern has to be cut off and rounded. The stored number is the nearest one that fits. For 0.1, that is a hair above the true tenth.

Flip the 64 bits yourself

Below are the real bits of a double. Tap a preset to load a number, or tap any bit to flip it. The red bit is the sign, the blue bits are the exponent (where the point sits) and the lime bits are the mantissa (the digits). The panel shows the exact value those bits stand for.

sign (1)exponent (11)mantissa (52)

Bits run left to right, biggest first. Tap a bit to flip it.

Shortest text that reads back as this number
The exact value actually stored

Load 0.5 and you will see an exact value with no trailing mess: a half is a power of two, so it fits perfectly. Load 0.1 and 0.2 and the exact values reveal tiny excesses, about 0.0000000000000000055 and 0.000000000000000011. Add them and the result lands on a double that is not the same one 0.3 rounds to. The two neighbours differ by a single bit at the very end of the mantissa, roughly 5.6 × 10−17.

Why programs print 0.1 and not the long truth

Languages show you the shortest decimal that would round back to the same double. That is why 0.1 prints as 0.1 even though the stored value is longer. The sum of 0.1 and 0.2 happens to be a different double from 0.3, so the shortest text that identifies it is 0.30000000000000004. The illusion of tidy decimals cracks only when two rounded values meet.

When a tiny error is not tiny

In 1991, during the Gulf War, a Patriot missile battery at Dhahran tracked time in tenths of a second using a 24-bit fixed-point register. The value 1/10 was chopped off at 24 bits, an error of about 0.000000095 per tick. After roughly 100 hours of continuous running the clock had drifted by about 0.34 seconds. A Scud travels at around 1,676 metres per second, so that gap moved the tracking window more than half a kilometre away from the target. The battery failed to engage, and 28 soldiers were killed.

What to do about it

Never test floating-point numbers for exact equality. Compare them with a small tolerance instead, such as checking that the difference is below 1e-9. For money, count whole cents as integers, or use a decimal type, so that "a tenth" really is a tenth. And remember that nothing is broken: every double is an exact value, just not always the one you were thinking of.