2009-05-31 45 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的回答是非常有用的,其實:)