2009-05-31 40 views
8

我在公司每天使用Python 2.4工作。我使用了标准数学库中的多功能对数函数'log',当我输入log(2 ** 31,2)时,它返回31.000000000000004,这让我觉得有点奇怪。Python中的不准确对数

我做了与2的其他权力相同的事情,它的工作完美。我跑了'log10(2 ** 31)/ log10(2)',我得到了一轮31.0

我试着在Python 3.0.1中运行相同的原始函数,假设它是在一个更高级版本中修复的。

为什么会出现这种情况? Python中的数学函数有可能存在一些不准确的情况吗?

+0

重复常年浮点问号(?为什么我收到的浮点错误),也无法找到最佳的重复Q可发布的,也许别人可以。 – 2009-06-01 13:55:22

+0

我应该指出,Python 3没有*修复了浮点错误。相反,打印输出使用智能算法来显示预期的浮点值,而不是松弛值。 – 2010-06-15 15:15:52

回答

44

这是与计算机算术的预期。它遵循特定规则,如IEEE 754,可能与您在学校学到的数学不匹配。

如果这个实际上很重要,请使用Python的decimal type

例子:

from decimal import Decimal, Context 
ctx = Context(prec=20) 
two = Decimal(2) 
ctx.divide(ctx.power(two, Decimal(31)).ln(ctx), two.ln(ctx)) 
+22

+1的一个很好的答案,但主要是“如果这实际上很重要。”探测器以较低的精度飞向土星。 – dwc 2009-05-31 14:15:26

+0

确实。斜体是答案中最重要的部分。 – 2009-05-31 14:22:33

17

始终假设浮点运算会有一些错误并检验采取这一错误顾及平等(一个百分比值,像0.00001%或为固定值像0.00000000001 )。这种不准确性是给定的,因为不是所有的十进制数都可以用二进制表示并具有固定数量的位精度。

如果Python使用IEEE754,那么您的特殊情况不是其中之一,因为31应该易于表示,即使是单精度。然而,它有可能在计算log 所花费的许多步骤之一中失去精度,原因很简单,因为它没有代码来检测像2的直接幂的特殊情况。

5

浮点运算从来都不准确。对于语言/硬件基础结构,它们返回具有可接受的相对误差的结果。

通常,假设浮点运算是精确的,尤其是单精度运算是错误的。 "Accuracy problems" section来自维基百科Floating point article :)

2

这是正常现象。我期望log10更精确,然后记录log(x,y),因为它知道对数的底数是什么,也可能有一些硬件支持计算基数为10的对数。

3

IEEE双浮点数有52 bits of precision。自从10^15年以来,双倍有15到16个有效数字。结果31.000000000000004对16个数字是正确的,所以它和你所期望的一样好。

1

python中的数字的repr表示(float.__repr__)尝试返回一串数字,尽可能接近真实值,因为IEEE-754算术精确到极限。在任何情况下,如果你print编的结果,你不会注意到:

>>> from math import log 
>>> log(2**31,2) 
31.000000000000004 
>>> print log(2**31,2) 
31.0 

print其参数转换为字符串(在这种情况下,通过float.__str__方法),这迎合了不准确的显示数字少:

>>> log(1000000,2) 
19.931568569324174 
>>> print log(1000000,2) 
19.9315685693 
>>> 1.0/10 
0.10000000000000001 
>>> print 1.0/10 
0.1 

usuallyuseless的回答是非常有用的,其实:)