2011-06-02 39 views
5

我有一個執行大量使用小數計算的系統,偶爾會加起來相同的號碼,但返回不同的結果,+/- 0.000000000000000000000000001另外的十進制順序會影響結果

下面是一個簡單的例子:

decimal a = 2.016879990455473621256359079m; 
decimal b = 0.8401819425625631128956517177m; 
decimal c = 0.4507062854741283043456903406m; 
decimal d = 6.7922317815078349615022988627m; 

decimal result1 = a + b + c + d; 
decimal result2 = a + d + c + b; 

Console.WriteLine((result1 == result2) ? "Same" : "DIFFERENT"); 
Console.WriteLine(result1); 
Console.WriteLine(result2); 

輸出:

DIFFERENT 
10.100000000000000000000000000 
10.100000000000000000000000001 

的差異是如此之小,沒有什麼實際作用,但有沒有人看到過類似本b安伏?我期望在合計相同的數字時,您總能得到相同的結果。

+10

這是StackOverflow中最常見的單一問題。 – 2011-06-02 23:11:11

+0

谷歌浮點不精確的表示,閱讀它的維基百科或搜索:) – sehe 2011-06-02 23:12:47

+0

值得一提的是'十進制'數據類型應該是免疫的四捨五入錯誤。 http://msdn.microsoft.com/en-us/library/system.decimal(v=vs.71).aspx – 2011-06-02 23:22:02

回答

7

Numerical analysis的整個領域致力於研究這些效果以及如何避免它們。

爲了在彙總浮點數列表時產生最佳結果,首先將列表中的數據從最小到最大排序,然後按照該順序將它們相加。

+0

由於他使用小數(而不是浮點數),這不是一個不同的問題? – 2011-06-02 23:26:10

+0

@Mark,'decimal'是一個浮點數,但是爲尾數分配的位數與指數的位數不同,爲處理貨幣提供了更好的工具。 「double」通常只有14位數字的精度,這就是在足夠的尾數的邊緣,以表示例如美國的赤字精確到百分之一美元。 「小數」可以代表兩倍以上的數字,但是由於指數較小,因此總體範圍小得多。 – sarnold 2011-06-02 23:31:06

+0

+1特別是關於排序的位。 :) – sarnold 2011-06-02 23:31:19

2

根據to MSDN,小數的精度爲28-29位。您的號碼中至少有一位是29位數字,因此您可能會超出限制。

2

您可能會懷疑某個decimal類型可以免受各地使用者的詛咒double

但是because decimal has 28-29 digits of precision並且您的輸入是要求29位數字精度的總和,您恰好處於您的數據類型可以精確表示的邊緣。

0

由於四捨五入的結果多個數字可能會有所不同,取決於他們的總結順序。這不會發生在數學上,但在你的例子中計算總和的順序很重要。 result += number;求和並將結果存儲在結果變量中。那時某些精度已經丟失。但是,如果我們按照相同的順序進行操作,它總會產生相同的結果。

Console.WriteLine(numbers.Sum()); // Always returns 9.214085249270111332166335344 

由於這許多程序使用銀行家舍入產生更接近的結果。請知道精度總是丟失。有沒有辦法來存儲compuiter MEMOR

Rounding

Bankers Rounding