2011-05-09 118 views
0

可能重複:
Why can't decimal numbers be represented exactly in binary?舍入誤差在C++

語言C++ 我聲明數組和我保存號(類型雙)在它。然後我開始比較數組中每個兩個元素之間的差異。 例如

a[1] = 0.05 
a[2] = 0.1 
a[3] = 0.15 

所以 當i執行以下

if(a[3] - a[2] == a[2] - a[1]) 

條件爲假!!

調試後,我發現,0.05保存在陣列中作爲 0.0499 ...... 993 和情況類似與0.10和0.15

我怎樣才能解決這個問題?

+5

一個有用的閱讀:[每個計算機科學家應該知道什麼關於浮點運算](http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html) – eldarerathis 2011-05-09 14:51:52

+6

Eleveny- bazillion重複。 – 2011-05-09 14:52:00

+0

參見:http:// floating-point-gui。de/ – hammar 2011-05-09 14:52:29

回答

2

浮點數學是計算機不會像您通常所期望的那樣給出結果的一個領域。請參閱this以供參考。

你可以做的是考慮像 delta = 0.00001
並檢查是否fabs((a[3]-a[2]) - (a[2]-a[1])) < delta

注意:如果這有什麼與貨幣或貨幣數據,那麼只需要使用/長等。使用浮點整數/雙待代表金錢是一件壞事,因爲上述原因,並在上面的鏈接中進一步解釋。

+0

「達到」標準「與它無關;浮點不精確是一個數學事實。如果你不想要後果,可以使用定點。當然,大多數主流語言不提供本地定點類型,這是一個缺陷。 – 2011-05-09 14:54:05

+1

它應該可能是abs((a [3] -a [2]) - (a [2] -a [1])) Mihai 2011-05-09 14:54:16

+0

你需要檢查**絕對**的價值差異對德爾塔 – Alnitak 2011-05-09 14:54:50

3

如果你想做精確的計算,你可能需要考慮使用有理數。有可能在C++中實現一個有理數的類。 Boost.Rational就是這樣的一個例子。

如果你想使用浮點數,你可能要爲「接近性」做比較,而不是平等的,就像這樣:

const float EPSILON = 0.0001; //< Some acceptable limit for equivalence 
float d1 = a[3] - a[2]; 
float d2 = a[2] - a[1]; 

if (fabs(d1 - d2) < EPSILON) { 
    // Consider d1 and d2 eqivalent 
} 
0

你有幾種選擇:

(1 )使用一個精確存儲這些數字的類型。對於這些數字,最簡單的可能是使用int並將它們存儲爲原始數字的100倍。

(2)找出比較雙打平等是一個不好的策略。看到,當你把數字存儲爲雙精度時,有一些數字在固定的位數中不能完全用二進制表示。 0.05(以及0.5 5 50等)就是其中的一個數字。