C#中的”四捨五入”--銀行家算法,即:四捨六入五取偶

很多人都知道Math.Round()是C#中用來做四捨五入,保留指定小數位的。但實際上它並不是真正的四捨五入,而是銀行家算法的“四捨六入五取偶”,事實上這也是IEEE的規範,因此所有符合IEEE標準的語言都應該採用這樣的算法。其規則如下:

  • 1、當捨去位的數值小於5時:直接捨去
  • 2、當捨去位的數值大於6時:進位加1
  • 3、當捨去位的數值等於5時,分兩種情況:

(1)若5後面有其他非0數字(即5不是最後一位)時,進位加1。

 (2)若5後面只有0(即5是最後一位)時,則根據5的前一位的奇偶來判斷,前一位爲奇數則進位加1,爲偶數則捨去。

遇到5需要捨去的情況只有一種,即5是最後一位有效數且前一位數是偶數。數字的精度越大,則這個算法就越像真正的四捨五入。

我們使用這個函數時,用來處理的數字通常是那些有n位小數的數字,而我們用於顯示的通常也就只有2-4位,所以這也就不容易發現這個問題。

可能純文字描述不太好理解,舉幾個例子:

  Math.Round(1.14, 1); //結果:1.1
  Math.Round(1.25, 1); //結果:1.2 五是最後一位且前一位爲偶數,也捨去
  Math.Round(1.15, 1); //結果:1.2 五是最後一位但前一位爲奇數,進位加一
  Math.Round(1.16, 1); //結果:1.2

如果希望實現中國式的標準的“四捨五入”法,應該怎麼辦呢?

從.NET 2.0 開始,Math.Round 方法提供了一個枚舉選項--MidpointRounding.AwayFromZero,可以用來實現傳統意義上的"四捨五入"。

即: 

Math.Round(4.5); //結果爲 4
Math.Round(4.5, MidpointRounding.AwayFromZero); //結果爲 5

結果爲 5。

MSDN文檔中這個MidpointRounding.AwayFromZero的描述是“當一個數字是其他兩個數字的中間值時,會將其舍入爲兩個值中絕對值較小的值。”

實際上從 .NET 2.0 發佈以來,網上已經有很多人都指出了這個翻譯錯誤(原文實際是 When a number is halfway between two others, it is rounded toward the nearest number that is away from zero.),實際上應該是取絕對值較大的值。可是很遺憾,.NET 3.0, .NET 3.5 的文檔中,這個翻譯錯誤依然沒有改正過來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章