2016-03-10 52 views
1

我服用幾個療程機器學習,我想了解這個問題的計算:瞭解數值穩定性大計算損失

variable = 1000000000 #1 billion 
for i in xrange(1000000): 
     variable = variable+ 1e-6 #0.000001 

variable = variable -1000000000 #1 subtracts with 1 billion again 
variable 
#>> 0.95367431640625 

應該1但真可謂0.95367431640625

有人能告訴我爲什麼會發生這種情況嗎?

+1

看起來像典型的浮點問題 - 計算機不能真正代表這些數字通過位,所以它變得「接近」,但你會得到一些錯誤和15或16位有效數字(小數點前9或10,小數點後6 )聽起來符合C語言中的'float'(我通常粗略地談論;我不知道具體情況,否則我會發布爲答​​案,而不是評論)。 – dwanderson

+0

此外,爲什麼這個標籤爲'performancecounter'?這似乎與「性能」沒有任何關係,而與準確性有關。 – dwanderson

+1

一些細節,以防止這個問題可以找到[這裏](http://stackoverflow.com/questions/11522933/python-floatingpoint-arbitrary-precision-available)。 –

回答

4

您正在失去精確度。這是因爲Python中的float實現了double floating point精度,這隻能保證精度高達15/16位數字。

當你這樣做:

1,000,000,000 + 0.000001 
1,000,000,000.000001 + 0.000001 
# and so on, note that you are adding the 16-th digit 
# but 1,000,000,000.000001 is not actually exactly 1,000,000,000.000001 
# behind is something like 1,000,000,000.000001014819 or 1,000,000,000.000000999819 

不斷,你破壞了精度的限制,也有在0.000001最後1其僅作爲0.000001代表經過一些其他值。因此你有累積的錯誤。

如果你將variable初始化爲0,情況就會不同。這是因爲在計算:

0.000000 + 0.000001 
0.000001 + 0.000001 
0.000002 + 0.000001 
#and so on 

雖然0.000001的實際值是不完全0.000001,但16個數字不精確遠離顯著號:

0.000000 + 0.00000100000000000000011111 
0.000001 + 0.00000100000000000000011111 #insignificant error 

你也可以避免錯誤使用decimal值,而不是double

from decimal import * 
variable = Decimal(1000000000) 
addition = Decimal(1e-6) 
for i in xrange(1000000): 
    variable = variable+ addition #0.000001 

variable = variable-Decimal(1000000000) #1 subtracts with 1 billion again 
variable 
+0

我該如何避免這種情況?並使python數到我想要的數字? –

+0

@AlvaroJoao使用'decimal',它具有更高的精度或者不要增加'1,000,000,000'開頭 – Ian

+0

@Ian我想他實際上並沒有增加到10億,然後只是減去10億,而是提供給我們一個MCVE(儘管誰知道)。 – dwanderson

1

Python的數學本身不能公頃ndle任意精度。如果你想更精確的結果,它看起來像你需要decimal模塊的工作,即使這樣,要小心:

from decimal import * 
x = Decimal(1000000000) 
y = Decimal(1e-6) 
z = x+y 
z 
##>> Decimal(1000000000.00000100000000000) 
w = z-x 
w 
##>> Decimal(0.000001000000000000) 

## however, when I tried: 
bad_x = Decimal(1000000000 + 1e-6) 
bad_x 
##>> Decimal(1000000000.0000009992934598234592348593458) 

原因bad_x變成了「錯誤」的價值,因爲它第一次在沒有正規ython除10000000001e-6,它們遇到了浮點問題,然後將該值(錯誤)傳遞給Decimal - 損壞已經完成。

爲您的使用情況下,它看起來像你可以使值到Decimal小號增加/減少,所以你應該得到想要的結果沒有問題。

+0

thta的聲音是解決這個問題的方法......謝謝 –