因为float基于ieee 754二进制浮点标准,无法精确表示0.1等十进制小数,实际存储为近似值;而decimal采用十进制字符串解析,可完全精确表示并运算,避免舍入误差。

为什么 float 算出来是错的,而 Decimal 就对?
因为 float 基于二进制 IEEE 754 表示,很多十进制小数(比如 0.1)根本无法精确存储——它实际存的是近似值。而 Decimal 是十进制浮点,按字符串解析字面量,直接保留你写的精度。
常见错误现象:0.1 + 0.2 == 0.3 返回 False;银行账务里 19.99 * 100 得到 1998.9999999999998 而不是 1999。
- 必须用字符串初始化:
Decimal('0.1')✅,Decimal(0.1)❌(此时传入的已经是失真后的float) - 所有参与运算的数值都得是
Decimal类型,混用float会立刻退化回精度丢失 -
Decimal不支持math.sqrt()这类函数,要用decimal.getcontext().prec控制全局精度,再调用.sqrt()方法
怎么设置并控制 Decimal 的精度?
精度不是“四舍五入”,而是运算过程中保留的有效位数。它影响除法、开方等无限位结果,也影响最终输出的位数。
- 设置全局精度:
decimal.getcontext().prec = 28(默认是 28,不是无限) - 局部覆盖精度:用
with decimal.localcontext() as ctx:块内临时改ctx.prec - 除法必须显式指定精度,否则报
decimal.DivisionImpossible(比如Decimal('1') / Decimal('3')) - 四舍五入策略可选:
ROUND_HALF_UP(常用)、ROUND_DOWN、ROUND_CEILING等,通过quantize()应用
示例:Decimal('1.2345').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) → Decimal('1.23')
和 float 混用时最常踩的三个坑
看似能跑,实则悄悄掉精度——这是最危险的情况。
- 把
Decimal和int相加没问题,但和float一加,整个结果变回float,精度立即崩坏 -
json.dumps()默认不认Decimal,直接报TypeError,得自己写default处理器转成str或float(后者又丢精度) - 数据库驱动(如
psycopg2、mysql-connector-python)通常把 DECIMAL 字段读成Decimal,但若你用float()强转再入库,就白用了
什么时候其实没必要用 Decimal?
不是所有小数场景都需要它。过度使用反而增加开销、降低可读性。
- 科学计算、图像处理、机器学习参数——这些本来就是近似模型,
float更快更通用 - 时间戳、坐标偏移量等相对值,误差在毫秒或像素级可接受,
float完全够用 - 配置文件里读出来的数字如果只做比较或索引(比如
timeout: 3.5),转成float更轻量
真正需要 Decimal 的,是那些“差一分钱都不能忍”的上下文:计费、会计、金融报价、税务计算——而且必须从输入源头(字符串)就开始守牢精度链。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











