Decimal是唯一能保证货币计算中数值相等性和末尾零语义的标准方案,因其十进制三元组存储天然支持有效位区分,而float因二进制表示导致0.1+0.2≠0.3等精度问题。

Decimal 是唯一能保证货币计算中“数值相等性”和“末尾零语义”不被破坏的标准方案。
浮点数 float 在底层用二进制表示,像 0.1、0.05、0.01 这类十进制小数根本无法精确存储。一次加法就可能引入误差,多次累加后误差放大,最终导致:
-
0.1 + 0.2 == 0.3返回False - 账户余额校验失败
- 对账差异无法归因
- 税额分摊结果错一位(比如该收
1.14却算成1.1399999999999999)
而 Decimal 从设计上就是十进制的:它把数字存为 (sign, coefficient, exponent) 三元组,天然支持“1.30 ≠ 1.3”这种有效位区分——这对发票、小票、银行流水至关重要。
必须用字符串初始化 Decimal
直接传 float 会把已有误差带进去:
-
Decimal('0.1')→ 正确:精确构造十进制0.1 -
Decimal(0.1)→ 错误:先用float解析出0.10000000000000000555...,再转成Decimal,误差已固化
整数安全:Decimal(100) 没问题,但涉及小数一律走字符串。
精度设置不是“保留几位小数”,而是“有效数字位数”
getcontext().prec = 6 表示所有运算最多保留 6 位有效数字,不是小数点后 6 位:
-
Decimal('123.456789') + Decimal('0.000123')→Decimal('123.456912')(共 6 位有效数字) - 货币场景通常设
prec = 28(默认值),真正控制小数位靠quantize()
别误以为设 prec = 2 就能当“两位小数用”,那会导致 1000 * 0.01 直接崩成 10(只留两位有效数字,10 就是两位)。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
舍入必须显式调用 quantize(),不能依赖 print 或 float 转换
显示或序列化前不 quantize(),就等于没做合规舍入:
-
total = Decimal('19.997') * Decimal('1.08')结果是Decimal('21.59676'),未四舍五入 - 正确做法:
total.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) -
float(total)或str(total)都不会自动截断或舍入,只是原样暴露内部精度
尤其注意:不同国家/场景舍入规则不同(如银行常用 ROUND_HALF_EVEN),必须显式指定,不能靠直觉。
避免与 float、int 混合运算
只要参与运算的一方是 float,整个表达式就会退化为 float 计算:
-
Decimal('10.5') + 0.1→ 先把Decimal转成float,再加,精度丢失 -
Decimal('10.5') + Decimal('0.1')→ 全程十进制,安全 - 连
len()、max()这类看似无关函数,若传入含float的列表,也得先统一转Decimal
最稳妥的做法:所有输入数据(数据库读取、API 返回、用户输入)在进入计算前,第一时间转成 Decimal 字符串再构造,杜绝隐式类型渗透。
关键点不在“能不能用”,而在于“只要漏掉一处字符串初始化、一次忘记 quantize、一个 float 混入,整条资金链路的可审计性就垮了”。这不是性能优化项,是财务系统的基础契约。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










