2011-03-03 104 views
2

我明白這個問題背後的原理,但它讓我很頭痛,認爲這在整個我的應用程序中都在發生,我需要找到解決方案。C#數學給出了錯誤的結果!

double Value = 141.1; 
double Discount = 25.0; 
double disc = Value * Discount/100; // disc = 35.275 
Value -= disc; // Value = 105.824999999999999 

Value = Functions.Round(Value, 2); // Value = 105.82 

我使用雙打代表相當小的數字。不知怎的,在計算141.1 - 35.275中,結果的二進制表示給出了一個只有0.0000000000001的數字。不幸的是,由於我將這個數字四捨五入,這給出了錯誤的答案。

我已經閱讀過有關使用小數而不是雙精度的方法,但是我無法用小數來替換Double的每個實例。有沒有更簡單的方法來解決這個問題?

+1

舍入爲3位小數,然後舍入爲2位小數?啊...並且要知道Math.Round使用Banker的四捨五入來循環,所以0。5時間縮短了一半,一半時間縮短了。有一個選項可以使用「標準」舍入。這是MidpointRounding.AwayFromZero。 – xanatos 2011-03-03 10:31:20

+1

由於我們在這裏討論的是貨幣數據,我認爲你應該儘快進行重構。 – linepogl 2011-03-03 10:33:56

回答

15

如果您正在尋找值十進制數的精確表示,您的需要替換doubledecimal無處不在。你只是使用了錯誤的數據類型。如果你整個地方都使用short,然後發現你需要處理比支持更大的值,你會怎麼做?這是一樣的交易。

但是,您應該真正瞭解開始的情況......例如,爲什麼Value不等於141.1。

我對這兩篇文章:

+1

+1因爲有一些預先寫好的書,以防萬一。 – 2011-03-03 10:33:09

0

而不是使用圓形圓的數量,你可以使用一些功能,你自己寫的,它使用一個小小量當四捨五入以允許錯誤時。這是你想要的答案。

你不想要的答案,但是我要說的是,如果你想要精確度,並且由於你正在用你的例子來判斷你的金錢,你應該不要使用二進制浮點數學。二進制浮點本質上不準確,有些數字不能正確表示。使用基數爲10的浮點的Decimal將是一個更好的方法,並且可以避免您在雙打中造成代價高昂的錯誤。

+4

他不應該使用*二進制*浮點類型。請注意,'decimal'也是一個浮點類型。還有一些數字不能準確表示......但所有*十進制*數字(在相關範圍和精度內)都可以準確表示。 – 2011-03-03 10:32:19

+0

感謝您的更正。編輯批准。 – Stewart 2011-03-03 12:05:32

3

您應該使用decimal - 這就是它的用途。

浮點運算的行爲?這正是它所做的。它具有有限的精確度。並非所有的數字都可以完全表示。事實上,有無限數量的實數值,只有有限的數字可以表示。 decimal對於這個應用程序的關鍵在於它使用基數10表示 - double使用基數2.

0

在花了大部分時間嘗試將每個「double」的實例替換爲「decimal」並實現I正在戰鬥失敗的戰鬥,我再看看我的回合功能。這可能是有用的那些誰也無法實現正確的解決方案:

public static double Round(double dbl, int decimals) {    
     return (double)Math.Round((decimal)dbl, decimals, MidpointRounding.AwayFromZero); 
    } 

通過首先將值強制轉換爲十進制,然後調用Math.Round,這將返回「正確」的價值。