PythonMastery

0.1 + 0.2 is not 0.3, and round(2.5) is 2

Floats are binary approximations, and round() rounds halves to the even number. Use math.isclose to compare and Decimal for money.

Two things surprise nearly everyone the first time: floats can't store most decimals exactly, and round() doesn't round halves the way you were taught at school.

The surprise

python
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(round(2.5), round(3.5), round(0.125, 2))
output
0.30000000000000004
False
2 4 0.12

Why it works

A float is stored in binary, and most decimal fractions (0.1 among them) have no exact binary form, in the same way 1/3 has no exact decimal form. The tiny errors are usually invisible, until you add two of them and compare with ==.

round() uses round half to even (banker's rounding): an exact half goes to the nearest even number. It's the IEEE 754 default because always rounding halves up adds a small upward bias to every total. So 2.5 goes to 2, 3.5 to 4.

The fix

Compare floats with a tolerance, and use Decimal for money, built from strings:

python
import math
from decimal import Decimal, ROUND_HALF_UP

print(math.isclose(0.1 + 0.2, 0.3))

price = Decimal("19.99")
print(price * 3)
print(Decimal("2.5").quantize(Decimal("1"), rounding=ROUND_HALF_UP))
output
True
59.97
3

Decimal("19.99") is exactly 19.99, so three of them is exactly 59.97. And when a rule really does say "halves go up", quantize with ROUND_HALF_UP says so explicitly.

When not to use it

Don't reach for Decimal in science or data work: floats are much faster, NumPy and pandas are built on them, and the errors are far smaller than any measurement you'll feed in. And never write Decimal(0.1) from a float; it faithfully copies the float's error:

python
from decimal import Decimal
print(Decimal(0.1) == Decimal("0.1"))
output
False

Learn it properly: Numbers in Depth: Integers, Floats, and the math Module