Python 3 decimal模块除法运算仍存在浮点精度误差问题咨询
问题核心原因
你遇到的现象不是decimal模块的bug,是两个认知误区导致的:
- 你定义的
a和b本身就不是严格互为倒数的数值。直接计算a*b就能验证:D('39.37007874') * D('0.0254')的实际结果是Decimal('0.999999999996'),和精确值1相差4e-13,本身就是近似的换算值,自然不可能通过1除以其中一个值精确得到另一个值。 - decimal模块默认使用28位有效数字的运算精度,遇到除法这类结果为无限小数的场景时,会按照当前设置的精度做舍入截断,不会无限制保留所有运算位。你看到的除法输出,是默认精度下的正确计算结果,不是运算错误。
对应解决方案
根据你的精度需求选对应方案即可:
- 如果只需要更高精度的十进制小数运算:直接调整decimal模块的上下文精度即可,示例代码如下:
from decimal import Decimal as D, getcontext # 根据需求设置有效数字位数,比如需要50位精度就设置为50 getcontext().prec = 50 a = D('39.37007874') b = D('0.0254') c = D('1') print(c / a) print(c / b)
注意:无论你把精度设置多高,因为你传入的a、b本身不是严格倒数,都永远无法得到c/a == b、c/b == a的结果,这是输入值本身的数学属性决定的,和运算工具无关。比如你做英寸和米的换算时,1英寸严格定义为0.0254米,1米对应的英寸值是无限循环小数,你手动取39.37007874这个有限位近似值,反算必然存在误差。
- 如果需要完全无精度损失的有理数运算:使用标准库的
fractions.Fraction类,它以分数(分子+分母)的形式存储有理数,只要是有理数都可以精确表示,不会有截断误差,示例代码如下:
from fractions import Fraction a = Fraction('39.37007874') b = Fraction('0.0254') c = Fraction(1, 1) print(c / a) # 输出精确分数形式,无任何精度损失 print(c / b)
内容的提问来源于stack exchange,提问作者GideonBear
相关产品推荐
相关产品推荐

