首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# Math.Round 銀行家四捨五入 (Banker's Rounding) 行為與解決方案

     編輯:關於C#

Math.Round 預設使用 銀行家四捨五入 (Banker's Rounding, MidpointRounding.ToEven):.5 時向最鄰近的偶數進位。這符合 IEEE 754 標準,可減少大量資料統計偏差,但常與業務預期的「四捨五入 (AwayFromZero)」不符。本文說明行為差異、正確用法與替代方案。

行為對照

程式碼預設 (ToEven)AwayFromZero業務預期
Math.Round(2.5, 0)233
Math.Round(3.5, 0)444
Math.Round(1.25, 1)1.21.31.3
Math.Round(-2.5, 0)-2-3-3

正確用法:明確指定 MidpointRounding

// 四捨五入 (遠離零)
Math.Round(2.5, 0, MidpointRounding.AwayFromZero); // 3
Math.Round(1.25, 1, MidpointRounding.AwayFromZero); // 1.3

// 銀行家四捨五入 (預設)
Math.Round(2.5, 0, MidpointRounding.ToEven); // 2
Math.Round(2.5); // 2 (隱含 ToEven)

.NET 版本差異

  • .NET Framework / .NET Core / .NET 5+:預設皆為 ToEven。
  • VB.NET:`Round` 函數預設為 `AwayFromZero` (可用 `MidpointRounding` 參數)。
  • SQL Server:`ROUND` 函數為 `AwayFromZero`。

常見替代方案比較

方法適用型別行為效能備註
Math.Round(v, d, AwayFromZero)double, decimal四捨五入高推薦標準做法
decimal.Round(v, d, AwayFromZero)decimal四捨五入高decimal 專用,精度更好
(long)Math.Floor(v + 0.5)double四捨五入 (正數)極高負數需特殊處理
v.ToString("F2")double, decimal四捨五入格式化中僅供顯示,回傳字串
Convert.ToInt32(v)double, decimal銀行家四捨五入高行為同 Math.Round 預設

金融/會計領域最佳實踐

  1. 全域統一:專案建立 `static class Rounding` 封裝 `RoundHalfUp` 方法,禁止直接呼叫 `Math.Round`。
  2. 使用 decimal:貨幣計算嚴禁使用 double/float,避免二進位浮點誤差(如 0.1 + 0.2 != 0.3)。
  3. 明確小數位:所有金額欄位固定小數位數 (如 2 位),儲存為 `decimal(18,2)`。
  4. 單元測試:針對 x.x5、負數、零、極大值建立測試案例。

程式碼範本

public static class Rounding
{
    /// 四捨五入 (遠離零),適用於金融計算
    public static decimal RoundHalfUp(this decimal value, int decimals = 2)
    {
        return decimal.Round(value, decimals, MidpointRounding.AwayFromZero);
    }

    /// 四捨五入到整數
    public static long RoundHalfUp(this decimal value)
    {
        return (long)decimal.Round(value, 0, MidpointRounding.AwayFromZero);
    }
}

// 使用
decimal price = 12.345m;
price.RoundHalfUp(2); // 12.35
price.RoundHalfUp();  // 12

結語

Math.Round 預設行為符合國際標準,但不符合大多數業務直覺。永遠明確指定 MidpointRounding.AwayFromZero,並搭配 decimal 型別進行貨幣計算,才能避免「少一分、多一分」的經典 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved