2011-07-31 72 views
1

好吧,我意識到這是早在一個星期天,所以我希望我只是缺少明顯的東西:C#Math.Round錯誤?

我有這樣的功能:

private decimal CashConversion(decimal amount, decimal ratio) 
{ 
    if (ratio == 1) return amount; 

    decimal convertedAmount = amount/ratio; 
    return Math.Round(convertedAmount, 2); 
} 

當我這樣稱呼它:

decimal tax = CashConversion(96.53, 15); 

「稅」變量等於6.43。但是,96.53/15是6.435333333333333。將其平分到2位應該返回6.44。我在這裏錯過了什麼嗎?

+0

類似於[爲什麼.NET使用銀行的舍入爲默認值?(http://stackoverflow.com/questions/311696/why-does-net-use-bankers作爲默認) – Eranga

+4

有些東西你沒有告訴我們你的代碼,因爲我得到6.44當[我嘗試](http://ideone.com/wHj19) –

+0

正如Ben Voigt所說,這不是代碼。首先,這是不正確的(你必須爲參數使用「decimal」值 - 你傳遞了一個'double')。修正後,確實返回'6.44'。您選擇的正確答案是錯誤的 - 銀行家的四捨五入僅適用於中點,因此它適用於「6.435」,而不適用於「6.4353」。請確保讓示例代碼儘可能接近您的實際代碼,並確保它確實能夠編譯,運行並顯示您正在討論的錯誤。您可能不會在實際代碼中持續使用「decimal」。 – Luaan

回答

3

檢查documentation for Math.Round:由於2是偶數,並且之後所述第二下一個數字爲5,則該值向下舍入,根據IEEE標準754,第4節。這就是所謂的銀行家舍入

這不是一個錯誤,而是一個預期的行爲。也許不是期待。

如果你想在 「數學上正確」 的行爲雖然,你可以調用Decimal.Round(Decimal, Int32, MidpointRounding)過載,如:

Math.Round(convertedAmount, 2, MidpointRounding.AwayFromZero); 
+1

那是一種什麼樣的垃圾?大聲笑。每個人都在小學初期就被教導,如果下一個數字是五,那麼它會被收集起來。我不能成爲第一個遇到這個問題的人,有沒有一種方式可以像C正常人那樣運行? – Scott

+0

啊,沒關係。閱讀文檔指向Decimal.Round。謝謝。 – Scott

+0

@Scoot,Math.Round有一個接受MidPointRounding參數的重載。 http://msdn.microsoft.com/en-us/library/ms131274.aspx – driis

3

這確實what is expected:6.435將輪至6.44:

當d恰好在兩個四捨五入的值之間,結果是 四捨五入的值,在[(十進制+1)十進制 位置]中有一個偶數位。例如,四捨五入到兩位小數時,值2.345 變爲2.34,值2.355變爲2.36 [和2.3653333變爲 2.37]。這個過程是已知的 四捨五入,甚至四捨五入到最近。

+0

6.4353仍然應該整理,因爲53> 50.我認爲數學.Round函數實際上是錯誤地指定的。 –

+0

確實。我寫了「[(小數+1)小數位]」代替「最右邊的小數位」,因爲這不正確地暗示數字中的最後一位小數位用於舍入目的,而不是第一位小數位四捨五入時將被刪除。 –

2

默認情況下,Math.Round使用銀行家的舍入。您可能期望它使用中點舍入。要強制此問題,請嘗試this

Math.Round(convertedAmount, 2, MidpointRounding.AwayFromZero); 
+2

不適用,'6.435333333333333'不在中點。 –