2013-10-21 49 views
-3

我嘗試在Python這個簡單的數學運算Python的數學精度

>>> math.floor(8.2-0.21) 
7.0 
>>> math.floor(8.21-0.2) 
8.0 
>>> math.floor(8.2-0.2) 
7.0 

第三個應該返回8,但它是返回7?

UPDATE

我已經嘗試在PHP,Ruby和JAVA,我已經得到了相同的結果。

更新2 我不知道爲什麼這個問題得到很多票下來!

+0

你的數學錯了我認爲......也許你想'math.round'? –

+2

你在每個人都回答你之後編輯它,但你的第三個例子是浮點錯誤。 – roippi

+0

我的意思是8.2 - 0.2,我已更新問題 – shox

回答

6

的語言您引用IEEE-754 64位二進制浮點或使用底層硬件的浮點,這可能是IEEE-754二進制浮點。

在IEEE-754 64位二進制浮點數中,8.2的最接近的可表示值是8.199999999999999289457264239899814128875732421875,最接近的可表示值爲0.2。200000000000000011102230246251565404236316680908203125.

所以,當你寫8.2 - 0.2,實際發生的事情是,0.200000000000000011102230246251565404236316680908203125從8.199999999999999289457264239899814128875732421875扣除。結果是略低於8的值,並且稍低於8的值的底面是7.

這裏的教訓是浮點算法通常是近似的,所以在評估具有不連續性的函數時您必須小心(比如地板)或陡坡。您必須設計代碼以接受可能跨越不連續點的結果,或者必須設計計算以避免跨越不連續點的錯誤。

+0

很好的回答,謝謝 – shox

+0

很好的回答... –

4

你的前兩個例子是可以預料的:

  • 8.2 - 0.217.997.99的樓層是7,這就是返回的內容。請記住,floor(x)是小於或等於x的最大整數。 8大於7.99,因此不可能被退回。另一方面,7符合此要求。

  • 8.21 - 0.28.018.01的地板是8 - 這裏沒有魔法。


>>> math.floor(8.2-0.2) 
7.0 

現在,這是更有趣。它有一個事實,即8.20.2不能準確地用輛彩車代表做,這樣計算的結果或許不是你可能有什麼想法:

>>> 8.2 - 0.2 
7.999999999999999 

再次,floor()工作as documented

你可以看到這個自己使用decimal爲:

>> from decimal import Decimal 
>>> Decimal(0.2) 
Decimal('0.200000000000000011102230246251565404236316680908203125') 
>>> Decimal(8.2) 
Decimal('8.199999999999999289457264239899814128875732421875') 

相關:What Every Computer Scientist Should Know About Floating-Point Arithmetic

+0

@EricPostpischil沒關係,你是對的 - 我在想0.8。該錯誤本身來自「8.2」和「0.2」。我會更新答案。 – arshajii

0

爲什麼它應該是8?樓層函數返回最近的整數向下捨去,所以這兩個例子都是正確的。

8.2 - 0.21 = 7.99,其向下舍入爲7

8.21 - 0.2 = 8.01Hz,其向下舍入爲8

0
>>> a=0.2 
>>> a 
0.20000000000000001 
>>> b = 8.2 
>>> b 
8.1999999999999993 
>>> b-a 
7.9999999999999991 
>>> math.floor(b-a) 
7.0 

由於浮點不精確