float会出错而decimal不会,因float在二进制下无法精确表示0.1等十进制小数,导致0.1+0.2≠0.3;decimal以十进制存储和运算,匹配金融“按位精确”需求,但需显式配置精度、舍入方式,并严格避免float输入。

为什么 float 会出错,而 decimal 不会?
浮点数在二进制下无法精确表示很多十进制小数(比如 0.1),0.1 + 0.2 == 0.3 返回 False 就是典型表现。金融计算要求“按位精确”,比如金额加减必须和人眼看到的十进制结果一致,不能有隐式舍入。
decimal 模块用十进制底数存储,所有运算都在十进制上下文中进行,天然匹配会计记账逻辑。但它不是“自动高精度”——精度由上下文控制,不设好照样出错。
必须显式设置 Context 和 rounding
默认的 decimal.DefaultContext 精度只有 28 位,且 rounding 是 ROUND_HALF_EVEN(银行家舍入),这在多数金融场景里不合适。
- 金融常用舍入方式是
ROUND_HALF_UP(四舍五入),需手动配置 - 金额通常保留 2 位小数,但中间计算可能需要更高精度(如利率计算到 6 位)
- 必须用
decimal.getcontext().prec = 28或创建局部decimal.Context控制精度
import decimal
decimal.getcontext().prec = 28
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
<h1>或更安全:用局部上下文避免污染全局</h1><p>ctx = decimal.Context(prec=28, rounding=decimal.ROUND_HALF_UP)
result = ctx.multiply(decimal.Decimal('19.99'), decimal.Decimal('1.08'))</p>
所有输入必须是字符串或 int,绝不能用 float
这是最常踩的坑:decimal.Decimal(0.1) 已经携带了 float 的误差,等价于 decimal.Decimal('0.1000000000000000055511151231257827021181583404541015625')。
- ✅ 正确写法:
decimal.Decimal('0.1')、decimal.Decimal('19.99')、decimal.Decimal(100) - ❌ 错误写法:
decimal.Decimal(0.1)、decimal.Decimal(float_var) - 如果从 JSON 或 CSV 读取数字,确保原始值是字符串字段,而非被 Python 自动转成 float
运算符重载可用,但要注意混合类型操作
decimal.Decimal 支持 +、-、*、/ 等运算符,但:
- 和
int运算没问题(decimal.Decimal('10') / 3) - 和
float运算会触发隐式转换,导致精度丢失(decimal.Decimal('10') / 0.3→ 先把0.3转成 Decimal,但此时它已是错误值) - 除法建议用
quantize()显式控制小数位:result.quantize(decimal.Decimal('0.01'))
真正难的不是调用 API,而是让整个数据流从源头开始就保持 decimal 字符串输入、全程不混入 float —— 这一点在对接 pandas、numpy 或 web 框架时最容易漏掉。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











