Jeff 隨手記

記下學習的點滴,它日回頭看來就是成長 ~

文章數(167) 回應數(1161) 引用數(0)

Round 真的是四捨五入嗎

2009/6/15 21:31 | 閱讀數 : 59286 2 人推薦 我要推薦 | 文章分類 : .Net隨手記 訂閱

在很多程式裡都有四捨五入Round的功能,但其四捨五入的結果是否真如預期?負數的四捨五入是什麼結果? 以下用JavaScript / .Net / Oracle /MS SQL /Excel  這幾種語言或工具來看看,結果都是出乎預料之外...

 
正數的四捨五入大都多什麼問題,問題在於負數,負數要怎麼四捨五入? 
 
JavaScript
Math.round(-0.51) = -1
Math.round(-0.5) = 0 <=竟然沒有進位!
Math.round(-0.49)=0
 
Math.round(0.51) = 1
Math.round(0.5) = 1
Math.round(0.49)=0
 
.Net
Math.round(-0.51)=-1
Math.round(-0.5) = 0<=竟然沒有進位!
Math.round(-0.49)=0
 
Math.round(0.51) = 1
Math.round(0.5) = 0<=負數沒進位就算了,正數也沒有進位!
Math.round(0.49)=0
 
Oracle
Select round(-0.51) from dual =-1
Select round(-0.5) from dual =-1
Select round(-0.49) from dual =0
 
Select round(0.51) from dual =1
Select round(0.5) from dual =1
Select round(0.49) from dual =0
 
MS Sql
Select top 1 round(-1.51,0) from testable =-2
Select top 1 round(-1.5,0) from testable =-2
Select top 1 round(-1.49,0) from testable =-1
 
Select top 1 round(1.51,0) from testable =2
Select top 1 round(1.5,0) from testable =2
Select top 1 round(1.49,0) from testable =1
註 : 這時有個怪現象,如果用0.X,會出現錯誤訊息.
錯誤訊息為 : 執行批次時發生錯誤。錯誤訊息為: 算術溢位。
因此,測試數據為1.51 / 1.5 / 1.49…<=MS SQL拒算0.X的小數字?
 
Excel
Round(-0.51) = -1
Round(-0.5) = -1
Round(-0.49) = 0
 
Round(0.51) = 1
Round(0.5) = 1
Round(0.49) = 0
 
 
  看了以上的清單後,或許有些人會覺得,怎麼.Net的結果這麼的奇怪,跟我們所認知的四捨五入不同,其實它沒有錯哦,這些只是誤會,從MSDN裡可以看到一點,它所遵循的是IEEE Standard 754第4節,這種捨入有時稱為捨入至最接近值。如果要捨入值為偶數,則捨去,如果為奇數,則進位,有看沒有懂哦,用下列幾個數字來解說一下.
 
0.5 =0
*因為要捨入值為偶數0,所以捨去0.5為0
1.5 = 2
*因為要捨入值為奇數1,所以進位0.5為2
2.5 = 2
*因為要捨入值為偶數2,所以捨去0.5為2
3.5 = 4
*因為要捨入值為奇數3,所以進位0.5為4
 
這個就是所謂的四捨六入五成雙(Banker’s Rounding)~
 
那要怎麼做才能達到我們”原本預期”的四捨五入?
.Net 2.0以上的Math.round多了一個MidpointRounding的參數可以傳入.
MidpointRounding.ToEven [Banker’s Rounding]
MidpointRounding.AwayFromZero [這就是大家小學所熟悉的四捨五入]
用法 :
Math.round(0.5,0,MidpointRounding.AwayFromZero) = 1
 >參考 :
MSDN Math.Round 方法
Math.Round 方法 (Decimal, MidpointRounding)


  • topcat 2009/6/15 下午 11:37 回覆

    # re: Round 真的是四捨五入嗎

    一個口訣:【四捨六入五成雙】

    當下一位是五的時候,進位與否主要是要讓最後成為雙數

    ^_^

  • yc421206 2009/6/16 上午 12:17 回覆

    # re: Round 真的是四捨五入嗎

    to topcat :

    這個四捨五入這議題還常被討論的耶~小弟也寫過一篇呢~

  • jeff-yeh 2009/6/16 下午 07:29 回覆

    # re: Round 真的是四捨五入嗎

    to topcat :

    剛開始第一次用.Net的Math.round,不知道它有這個情況,結果整個debug的半死....

  • ian 2009/6/16 下午 08:20 回覆

    # re: Round 真的是四捨五入嗎

    這個round,在asp時代也是令很多人傻眼的勒

    最後乾脆寫成數學式,統一先加0.5後,無條件取整數

    哈,也算是一招

  • jeff-yeh 2009/6/16 下午 08:28 回覆

    # re: Round 真的是四捨五入嗎

    to ian :

    這個還要注意到,可能是負數的四捨五入.

    不過今天同事用一招.ToString("0.#")的方式.

    這是可以四捨五入,不過Boxing/Unboxing....看個人囉~

  • yc421206 2009/6/18 下午 10:57 回覆

    # re: Round 真的是四捨五入嗎

    to jeff-yeh :

    http://www.dotblogs.com.tw/yc421206/archive/2008/11/03/5852.aspx

    這裡也有!!

     

  • jeff-yeh 2009/6/18 下午 11:22 回覆

    # re: Round 真的是四捨五入嗎

    to yc421206 :
    Ok~Ok~感謝贊助~

  • teng-hong 2014/4/29 下午 10:35 回覆

    # re: Round 真的是四捨五入嗎

    其實就數學上來看-0.5進位就是0啊

    因為0比-1大, 如果-0.5歸給-1那是屬於"捨去"

    麻煩大大在紙上畫一個數線, 然後再把這個問題想看看

    其實程式這樣跑才是正確的

     

    至於.Net的0.5不進位成1, 的確在邏輯上是說不過去的

    不過在以前VB6裡的round函數就有奇進偶不進的奇異現象

    到了.Net不知道是只有VB會發生,還是連VS C++.C#都會有這種狀況呢?

標題 *
名稱 *
Email (將不會被顯示)
Url
回應
登入後使用進階評論
Please add 7 and 2 and type the answer here: