Python 3十进制模块除法仍然存在浮点错误



在python中使用decimal模块时,似乎除法仍然给出不准确的结果。这是我用来检查这个的代码,我做错了什么,或者是不可能用十进制模块精确地做除法?在这种情况下,有没有别的东西可以让我精确地进行这种计算?

from decimal import Decimal as D
a = D('39.37007874')
b = D('0.0254')
c = D('1')
print(c / a) #0.02540000000010160000000040640   unexpected
print(c / b) #39.37007874015748031496062992     unexpected
print(c * b) #0.0254                            expected
print(c * a) #39.37007874                       expected

您可以通过设置全局上下文(用于中音操作,如c / a)或使用Context实例执行以下操作来提高十进制上下文的精度:

>>> from decimal import Decimal, Context, getcontext
>>> Decimal('1') / Decimal('0.0254')
Decimal('39.37007874015748031496062992')
>>> getcontext().prec
28
>>> getcontext().prec = 56
>>> Decimal('1') / Decimal('0.0254')
Decimal('39.370078740157480314960629921259842519685039370078740157')
>>> ctx = Context(prec=28)
>>> ctx.divide(Decimal('1'), Decimal('0.0254'))
Decimal('39.37007874015748031496062992')
>>> ctx = Context(prec=56)
>>> ctx.divide(Decimal('1'), Decimal('0.0254'))
Decimal('39.370078740157480314960629921259842519685039370078740157')

正如其他人指出的那样,39.37007874 * 0.0254 != 1所以你对结果的期望可能是不正确的:

>>> from decimal import Decimal, Context
>>> ctx = Context(prec=1000000)
>>> ctx.multiply(Decimal('0.0254'), Decimal('39.37007874'))
Decimal('0.999999999996')

您可以简单地使用round函数并得到您需要的任何小数。

from decimal import Decimal as D
a = D('39.37007874')
b = D('0.0254')
c = D('1')
print(round(c / a, 8)) #0.02540000
print(round(c / b, 8)) #39.37007874
print(round(c * b, 8)) #0.02540000
print(round(c * a, 8)) #39.37007874 

您可能需要使用fractions

from fractions import Fraction
a = Fraction('39.37007874')
b = Fraction('0.0254')
c = Fraction(1)
print(c / a)  # 50000000/1968503937
print(c / b)  # 5000/127
print(c * b)  # 127/5000
print(c * a)  # 1968503937/50000000

这将使除法尽可能准确,尽管其他操作,如sqrt()sin()仍然与float一样准确。