01Why it matters
Why 0.1 + 0.2 isn’t 0.3
Type 0.1 + 0.2 into Python or a browser console and you get 0.30000000000000004. Nothing is broken: computers
store real numbers in a fixed number of bits, so most decimals can only be stored approximately, and the tiny errors
show up when you add them.
Once you can read the bits, the surprises become predictable: which numbers are exact, how big the error can be, and why
you should never compare two floats with ==.
02Key parts
The pieces you will see
- sign bit
- Bit 31: 0 for positive, 1 for negative.
- exponent
- Bits 30–23, an integer from 0 to 255. The power of two is (the bias makes negative powers possible).
- fraction
- Bits 22–0: the binary digits after the point. A hidden 1 sits in front, so a float32 has 24 significant bits.
- gap (ulp)
- The distance to the next float. Nothing in between can be stored, so a number is rounded to the nearest float.
A float32 is scientific notation in base 2:
03See it work
Take 0.1 apart
In binary, is , repeating forever, just as is in decimal. A fraction has a finite binary form only if its denominator is a power of two, and isn't. So the 23 fraction bits cut the pattern off, and the stored value is the nearest float:
Larger numbers have larger gaps. Above the gap is 2, so even a whole number can fall between floats:
04Predict
Your turn: is 0.75 exact?
Make 5 predictions: step forward and answer each question before the next step plays.
0 of 5 made05Try it
Try the edges
Type your own numbers into the box, or pick an example:
- 0.1 + 0.2: the sum is done in float64 first, giving , and then rounded to float32. That float64 error is far smaller than a float32 gap, so it lands on the very same float32 as . In float64 the two differ by one gap, which is the famous result. Whether two computed values compare equal depends on the precision and the rounding, not on the maths.
- 1e-40: too small for a normal float. The exponent bits are all 0, the hidden 1 disappears, and precision fades gradually (a subnormal).
- Infinity, NaN and −0: special patterns with an all-ones or all-zeros exponent.
06Check yourself
Check yourself
Question 1 of 4
The exponent bits of a float32 read 10000010 (130). What power of two does it multiply by?
Your answer comes back in Review in a few days, so it sticks.
Question 2 of 4
Why can’t 0.1 be stored exactly in binary?
Question 3 of 4
How far apart are neighbouring float32s around 2²⁴ = 16 777 216 (just above it)?
Question 4 of 4
What is the safest way to check whether a computed total equals 0.3?
07Explain it back
Say it in your own words
How does a float store a number like 0.1, and why do sums such as 0.1 + 0.2 come out slightly off?
08Recap
What to remember
- A float32 is a sign, a power of two () and 24 significant bits (one of them hidden).
- Most decimals, like 0.1, repeat forever in binary and are rounded to the nearest float.
- The gap between floats grows with the number: about 7 significant digits in float32, 16 in float64.
- Never compare floats with
==; use a tolerance. Subnormals, ±0, ∞ and NaN cover the edges.