decimal是唯一能保证数值相等性和末尾零语义的方案;必须用字符串初始化(如decimal('0.1')),避免float解析误差;prec控制有效数字而非小数位,货币计算应默认28并用quantize(decimal('0.01'), rounding=round_half_up)强制舍入。

因为 float 在底层用二进制表示十进制小数,像 0.1、0.05、0.01 根本无法精确存储,一次加法就可能引入误差,多次累加后对账失败、余额校验不通过、税额错一位——而 Decimal 是唯一能同时保证“数值相等性”和“末尾零语义”的标准方案。
Decimal('0.1') 和 Decimal(0.1) 的区别
这是最常踩的坑:前者精确构造十进制 0.1;后者先用 float 解析出 0.10000000000000000555...,再转成 Decimal,误差已固化。
- ✅ 正确:
Decimal('0.1')、Decimal('19.99')、Decimal('1000') - ❌ 错误:
Decimal(0.1)、Decimal(19.99)(哪怕 19.99 看似“整”) - ⚠️ 整数安全:
Decimal(100)没问题,但只要含小数点,一律走字符串初始化
getcontext().prec = 2 是常见误解
prec 控制的是“有效数字位数”,不是“小数点后几位”。设成 2 会导致 Decimal('1000') * Decimal('0.01') 直接崩成 Decimal('10')(10 只有两位有效数字),而不是你想要的 10.00。
- 货币场景通常保留默认
prec = 28,真正控制小数位靠quantize() - 需要两位小数时,用
.quantize(Decimal('0.01')),不是调prec - 不同国家舍入规则不同(如银行常用
ROUND_HALF_EVEN),必须显式传rounding=参数
quantize() 不是可选操作,而是强制步骤
print()、str()、float() 都不会自动舍入。比如 Decimal('19.997') * Decimal('1.08') 结果是 Decimal('21.59676'),直接入库或显示就等于把未合规舍入的数据交出去。
- ✅ 正确:
total.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) - ❌ 错误:
str(total)、float(total)、甚至f"{total}" - ⚠️ 注意:
quantize()的模板参数必须是Decimal类型,Decimal('0.01')不能写成'0.01'或0.01
真正难的不是学会用 Decimal,而是把“所有输入都走字符串初始化”“所有输出前必 quantize()”变成肌肉记忆——漏掉任意一环,精度就归零。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











