numpy floating point errors: 0.1 + 0.2, isclose, arange (tested)

Floating point errors in numpy come from binary floats: 0.1 + 0.2 is 0.30000000000000004, so compare with np.isclose (mind its default atol=1e-08 for tiny values), and use np.linspace instead of float-step np.arange, which can include the stop value.

1. The common surprises, measured

Run with python b1.py:

import sys
import numpy as np

print("numpy", np.__version__, "python", sys.version.split()[0])
a = np.array([0.1, 0.2, 0.3])
print("0.1 + 0.2 == 0.3:", a[0] + a[1] == a[2])
print("0.1 + 0.2 =", repr(a[0] + a[1]))
print("np.isclose(0.1 + 0.2, 0.3):", np.isclose(a[0] + a[1], a[2]))

print("np.arange(1, 1.3, 0.1):", np.arange(1, 1.3, 0.1))
print("np.linspace(1, 1.2, 3):", np.linspace(1, 1.2, 3))

print("isclose(1e-10, 0):", np.isclose(1e-10, 0), "| with atol=0:", np.isclose(1e-10, 0, atol=0))
print("isclose(1e-10, 2e-10):", np.isclose(1e-10, 2e-10), "| with atol=0:", np.isclose(1e-10, 2e-10, atol=0))
print("allclose([1, 2], [1, 2 + 1e-9]):", np.allclose([1.0, 2.0], [1.0, 2.0 + 1e-9]))

print("np.float32(0.1) == 0.1:", np.float32(0.1) == 0.1, "| float32 value:", np.float32(0.1).item())
print("np.float32(0.1) == np.float64(0.1):", np.float32(0.1) == np.float64(0.1))
print("np.round(2.5), np.round(3.5):", np.round(2.5), np.round(3.5))
print("np.sum(ten 0.1s):", np.sum(np.full(10, 0.1)), "| loop:", end=" ")
t = 0.0
for _ in range(10):
    t += 0.1
print(t)

Output:

numpy 2.5.4 python 3.13.5
0.1 + 0.2 == 0.3: False
0.1 + 0.2 = np.float64(0.30000000000000004)
np.isclose(0.1 + 0.2, 0.3): True
np.arange(1, 1.3, 0.1): [1.  1.1 1.2 1.3]
np.linspace(1, 1.2, 3): [1.  1.1 1.2]
isclose(1e-10, 0): True | with atol=0: False
isclose(1e-10, 2e-10): True | with atol=0: False
allclose([1, 2], [1, 2 + 1e-9]): True
np.float32(0.1) == 0.1: True | float32 value: 0.10000000149011612
np.float32(0.1) == np.float64(0.1): False
np.round(2.5), np.round(3.5): 2.0 4.0
np.sum(ten 0.1s): 1.0 | loop: 0.9999999999999999

2. What each line means and what to do

To find where a calculation produces inf or nan (overflow, divide by zero), see numpy errstate. For exact decimal arithmetic (money), use Python's decimal module instead of floats.

Related: numpy polyfit RankWarning ยท numpy LinAlgError: Singular matrix.

Frequently asked questions

Why is 0.1 + 0.2 not equal to 0.3 in numpy?

The decimals have no exact binary representation; the float64 sum is 0.30000000000000004. Compare with np.isclose or np.allclose instead of ==.

Why does np.arange include the stop value?

With a float step the number of elements is computed from rounded values, so np.arange(1, 1.3, 0.1) returned [1. 1.1 1.2 1.3]. Use np.linspace(start, stop, num).

Why does np.isclose say 1e-10 equals 2e-10?

The default atol=1e-08 dominates for tiny numbers. Pass atol=0 (or an appropriate scale) so only rtol applies.

Written with AI assistance. Measured on 2026-10-23 with numpy 2.5.4 and Python 3.13.5 on Linux. The script was run verbatim and the output pasted unedited. PlainTables is our extension; numpy is free.