Floats and equality
The gotcha
0.1 + 0.2 != 0.3. IEEE 754 double-precision floats can’t represent most decimal fractions exactly. Equality comparison fails for values that “should” be equal.
Minimal repro
0.1 + 0.2 # 0.30000000000000004
0.1 + 0.2 == 0.3 # False
# Underlying:
from decimal import Decimal
Decimal(0.1)
# Decimal('0.1000000000000000055511151231257827021181583404541015625')
The literal 0.1 is not the rational 1/10 — it’s the nearest representable double. Same for 0.2 and 0.3. The closest doubles to 0.1 and 0.2 add up to a number whose closest double is not the closest double to 0.3.
Why it happens
Floats use a binary radix. 0.1 decimal has no terminating binary representation (like 1/3 has no terminating decimal). The runtime stores 53 bits of mantissa, which is the closest possible — but rounding errors accumulate across operations.
Special values to know:
float("inf"),float("-inf"),float("nan")— finite arithmetic doesn’t always behave:nan != nanis True.0.0 == -0.0is True but1/0.0raises and1/-0.0raises (in Python; in C they’d be ±inf).True / 0raisesZeroDivisionError.
How to avoid
For tolerant equality:
import math
math.isclose(0.1 + 0.2, 0.3) # True
math.isclose(a, b, rel_tol=1e-9, abs_tol=0.0)
For exact decimal arithmetic (money, etc.), use Decimal:
from decimal import Decimal, getcontext
Decimal("0.1") + Decimal("0.2") == Decimal("0.3") # True
Pass strings to Decimal, not floats — Decimal(0.1) inherits the float’s imprecision.
For NaN-safety:
import math
math.isnan(x) # only correct way to test for NaN
Interview angle
“What does 0.1 + 0.2 == 0.3 evaluate to, and why?” Follow-up: “How would you compare two floats safely?” Bonus: “Is nan == nan True?” (No — IEEE 754 says NaN is not equal to anything, including itself.)