浮点数比较不可用 ==,应使用 math.isclose()(单值)或 numpy.allclose()(数组),二者容差默认值与 nan 处理不同,自定义函数需注意类型安全与边界。

浮点数直接用 == 比较会出错
Python 中 0.1 + 0.2 == 0.3 返回 False,不是 bug,是二进制浮点表示的固有限制。IEEE 754 标准下,很多十进制小数无法精确存储,比较前必须引入容差(tolerance)。
实操建议:
- 永远别对
float类型用==做逻辑判断,尤其是从计算、文件读取或 API 返回得到的数值 - 用
math.isclose()替代,它默认使用相对容差rel_tol=1e-09和绝对容差abs_tol=0.0 - 当比较接近零的数(比如
-1e-15和0.0),必须显式设abs_tol,否则rel_tol失效
示例:math.isclose(0.1 + 0.2, 0.3, abs_tol=1e-10) → True
numpy.allclose() 和 math.isclose() 的区别在哪
math.isclose() 只能比两个标量;numpy.allclose() 是批量比较数组,但默认行为更“宽松”——它同时检查相对和绝对容差,并且对 NaN 的处理不同。
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 比较单个数值对,优先用
math.isclose()(标准库,无依赖) - 比较
ndarray或需要广播语义时,用numpy.allclose(),注意它默认rtol=1e-05,atol=1e-08,比math.isclose()宽松得多 - 若数组含
nan,numpy.allclose(a, b)默认返回False;加参数equal_nan=True才把对应位置的nan视为相等 - 不要混用:用
numpy.allclose()比两个 Pythonfloat,它会转成 0 维数组,但语义不清晰,易误导
自定义容差比较函数要注意什么
有些场景(比如物理模拟、金融计算)需要固定绝对容差(如 ±0.0001 元),或混合策略,这时常写自定义函数。但容易忽略边界和类型安全。
实操建议:
- 避免直接写
abs(a - b) :当 <code>a或b是inf或nan时,结果不可靠 - 先做类型检查:用
isinstance(x, (int, float)),防止传入字符串或Decimal导致静默错误 - 对
inf单独处理——inf == inf是True,但abs(inf - inf)是nan - 如果要兼容
Decimal或高精度需求,别硬套浮点容差逻辑,改用decimal.Decimal.quantize()或专用库如pytest.approx()
pytest.approx() 在测试里怎么用才不翻车
写单元测试时,pytest.approx() 是最常用的容差断言工具,但它不是函数调用,而是一个可比较对象,行为和直觉略有偏差。
实操建议:
-
assert a == pytest.approx(b)合法;但assert pytest.approx(b) == a也合法——它重载了__eq__,左右对称 - 容差值是通过
pytest.approx(b, abs=1e-6)传入,不是tol参数;漏写abs=会导致用默认相对容差,在b ≈ 0时失效 - 支持列表、元组、嵌套结构:
assert [1.001, 2.002] == pytest.approx([1, 2], abs=0.01) - 不能用于
in判断(如x in [pytest.approx(1), pytest.approx(2)]),会报TypeError;此时应改用any(math.isclose(x, y) for y in [1,2])
真正麻烦的从来不是“要不要容差”,而是“容差该设多大”——这取决于数据来源、计算路径长度、以及业务上“算对了”的定义。没统一答案,但每次写比较前,至少得问一句:这个 1e-9 是抄来的,还是算出来的?










