直接回答:float 遵循 IEEE 754 双精度标准,用 52 位二进制尾数表示小数,而 0.1、0.2 在二进制下是无限循环小数,只能截断存近似值;两个近似值相加得到 0.30000000000000004,与 0.3 自身的近似值不同,所以 == 比较失败。这不是 Python 的 bug,所有使用二进制浮点的语言(C、Java、JS)都有同样行为。

from decimal import Decimal

0.1 + 0.2 == 0.3              # False
Decimal("0.1") + Decimal("0.2") == Decimal("0.3")  # True
Decimal(0.1)   # 危险:先把 0.1 变成 float 的近似值再转

展开解析:金额处理有三种主流方案。一是用 decimal.Decimal:十进制运算、可设精度和舍入模式(ROUND_HALF_UP 等),注意必须用字符串构造,否则误差在构造前就已引入。二是直接以"分"为单位存整数:最快且无精度问题,适合内部高频流转,只在展示层除以 100。三是科学计算场景用 math.isclose(a, b, rel_tol=1e-9) 容忍误差比较,适合物理量但不适合财务——财务要求的是精确到分的确定性,而不是"足够接近"。另外要注意 float 转 str 时 Python 3.1 起用最短往返表示(repr 算法),打印出来的 0.1 其实只是显示层面的"好看",内部仍是近似值。

实践要点:Decimal 的全局上下文 getcontext().prec 默认 28 位有效数字,财务场景配合 quantize(Decimal("0.01")) 定标,避免 1.005 这类值在不同精度下舍入不一致;数据库一侧对应 DECIMAL/NUMERIC 类型,不要用 FLOAT/DOUBLE,否则读写边界又会引入二进制误差。

追问方向:为什么 Decimal(0.1)Decimal("0.1") 不相等?二进制浮点的"安全整数"上限是多少?

(约 480 字)