Python中默认的float类型是双精度浮点数,遵循IEEE 754标准,在计算过程中会因为二进制存储的特性出现精度丢失的问题,而decimal模块通过十进制浮点运算的方式,可以实现可配置的高精度计算,解决这类精度偏差问题。

decimal模块基础使用
使用decimal模块前需要先导入模块,核心的类是Decimal,我们可以通过字符串或者整数来初始化Decimal对象,避免直接用float转换带来的精度问题。
from decimal import Decimal
# 正确的初始化方式,使用字符串传入数值
a = Decimal('0.1')
b = Decimal('0.2')
print(a + b) # 输出0.3,没有精度偏差
# 错误的方式,用float转换会保留原有精度问题
c = Decimal(0.1)
d = Decimal(0.2)
print(c + d) # 输出0.3000000000000000166533453694
调整计算精度
decimal模块默认的精度是28位,我们可以通过getcontext()方法获取当前上下文,修改精度参数来满足不同场景的需求。
from decimal import Decimal, getcontext
# 设置精度为10位
getcontext().prec = 10
a = Decimal('1')
b = Decimal('3')
print(a / b) # 输出0.3333333333,只保留10位有效数字
设置舍入规则
在进行除法运算或者需要保留固定小数位数的场景中,我们可以通过设置舍入规则来控制结果的取值方式,decimal模块内置了多种舍入模式。
from decimal import Decimal, ROUND_HALF_UP, getcontext
# 设置舍入规则为四舍五入
getcontext().rounding = ROUND_HALF_UP
# 计算1除以6,保留2位小数
result = Decimal('1') / Decimal('6')
# 使用quantize方法保留2位小数
print(result.quantize(Decimal('0.00'))) # 输出0.17
decimal模块常见使用场景
金融计算场景
金融场景中涉及金额的计算对精度要求极高,哪怕一分钱的偏差都会引发账务问题,这时候必须使用decimal模块替代float。
from decimal import Decimal, ROUND_HALF_UP
# 商品单价、数量、折扣
price = Decimal('19.99')
count = Decimal('3')
discount = Decimal('0.85')
# 计算总价,保留2位小数
total = price * count * discount
final_total = total.quantize(Decimal('0.00'), rounding=ROUND_HALF_UP)
print(f'最终应付金额:{final_total}') # 输出最终应付金额:50.97
科学统计场景
在科学计算中如果需要多次迭代运算,float的精度偏差会不断累积,使用decimal模块设置足够的精度可以保证计算结果的可靠性。
需要固定小数位的场景
比如税率计算、百分比统计等场景,需要固定保留几位小数,decimal的quantize方法可以精准控制小数位数,避免手动格式化带来的问题。
注意事项
- 初始化Decimal对象时尽量使用字符串,不要直接使用float,否则会带入float本身的精度问题
- 不同场景需要设置合适的精度和舍入规则,不需要盲目设置过高的精度,会增加计算开销
- decimal模块的计算速度比float慢,如果是不需要高精度的普通计算场景,还是优先使用float类型
decimal模块是Python处理高精度计算的首选方案,只要合理设置精度和舍入规则,就能满足绝大多数对精度有要求的业务场景需求。