0.1 + 0.2 ≠ 0.3 是因 ieee 754 二进制浮点数无法精确表示十进制小数,导致精度丢失;应使用 decimal('0.1') 字符串初始化,避免 decimal(0.1);运算中禁用 float 混用,控制精度需用 localcontext() 设置 prec 和 rounding。

为什么 float 类型算 0.1 + 0.2 ≠ 0.3?
这不是 Python 的 bug,而是 IEEE 754 双精度浮点数在二进制下无法精确表示十进制小数(比如 0.1 实际存储为近似值)。结果就是:0.1 + 0.2 == 0.3 返回 False。金融计算、科学测量等场景必须避免这种误差。
根本原因在于底层用二进制存储,而很多有限十进制小数是无限二进制小数 —— 就像 1/3 在十进制里是 0.333… 一样。
decimal 模块怎么初始化才不踩坑?
直接用 Decimal('0.1'),别用 Decimal(0.1)。后者会先让 float 解析 0.1 成二进制近似值,再转成 Decimal,误差已经进来了。
-
Decimal('0.1') + Decimal('0.2')→ 精确得到Decimal('0.3') -
Decimal(0.1) + Decimal(0.2)→ 得到类似Decimal('0.3000000000000000444089209850062616169452667236328125') - 字符串初始化是唯一安全入口;整数、
Fraction也可,但字符串最常用也最可控
如何控制全局精度和舍入方式?
decimal 默认精度是 28 位,但这个“精度”指**有效数字位数**,不是小数点后几位。实际计算中常需显式设置上下文,否则容易误判结果长度或舍入行为。
推荐做法:用 localcontext() 临时修改,避免污染全局:
from decimal import Decimal, localcontext
<p>with localcontext() as ctx:
ctx.prec = 6 # 总共最多 6 位有效数字
ctx.rounding = 'ROUND_HALF_UP'
result = Decimal('1.2345678') + Decimal('2.3456789')</p><h1>result 是 Decimal('3.58025'),不是 '3.580247'</h1>
- 不要直接改
getcontext().prec,多线程下会互相干扰 -
ROUND_HALF_UP是四舍五入(日常会计常用),区别于默认的ROUND_HALF_EVEN(银行家舍入) - 精度设太高(如 100)不会提升准确度,只影响中间计算保留位数;设太低会过早截断
decimal 和 float 混用会出什么问题?
只要出现 +、-、*、/ 等运算符,Python 会尝试把 Decimal 转成 float 再算 —— 一旦转成 float,精度就彻底丢了。
- 错误写法:
Decimal('1.1') + 2.5→ 结果是float,且2.5还算干净,但0.1就不行 - 正确写法:
Decimal('1.1') + Decimal('2.5')或Decimal('1.1') + Decimal(25).scaleb(-1) - 输入来源是 JSON / CSV / 用户表单时,务必统一用字符串转
Decimal,别信float(input_str)
真正难的不是调用 Decimal,而是守住所有输入出口和中间转换边界 —— 少一次隐式 float 转换,就少一个精度漏洞。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











