Dot-Net

為什麼.NET 預設使用銀行家的四捨五入?

  • November 22, 2008

根據文件,該decimal.Round方法使用對大多數應用程序不常見的取整算法。所以我總是最終編寫一個自定義函式來執行更自然的四捨五入算法:

public static decimal RoundHalfUp(this decimal d, int decimals)
{
   if (decimals < 0)
   {
       throw new ArgumentException("The decimals must be non-negative", 
           "decimals");
   }

   decimal multiplier = (decimal)Math.Pow(10, decimals);
   decimal number = d * multiplier;

   if (decimal.Truncate(number) < number)
   {
       number += 0.5m;
   }
   return decimal.Round(number) / multiplier;
}

有人知道這個框架設計決定背後的原因嗎?

框架中是否有任何內置的半舍入算法實現?或者也許是一些非託管的 Windows API?

decimal.Round(2.5m, 0)對於只寫期望 3 結果卻得到 2的初學者來說,這可能會產生誤導。

可能是因為它是一個更好的算法。在執行多次舍入的過程中,您將平均得出所有 0.5 的最終舍入均等。例如,如果您要添加一堆四捨五入的數字,這可以更好地估計實際結果。我會說,即使這不是某些人所期望的,但這可能是更正確的做法。

其他解釋為什麼銀行家的算法(又名四捨五入到偶數)是一個不錯的選擇的原因是非常正確的。在最合理的分佈上,它不會像零差一半方法那樣受到負偏或正偏的影響。

但問題是 .NET 為什麼預設使用 Banker 的實際舍入 - 答案是 Microsoft 遵循IEEE 754標準。這也在MSDN for Math.Round的備註下提到。

另請注意,.NET 通過提供MidpointRounding枚舉來支持 IEEE 指定的替代方法。他們當然可以提供更多解決關係的替代方案,但他們選擇只滿足 IEEE 標準。

引用自:https://stackoverflow.com/questions/311696