none
vb.net Math.Round ToEven,AwayFromZero 小數點後四位為什麼輸出的結果與預期的不同 RRS feed

  • 問題

  • 我看過 http://msdn.microsoft.com/zh-tw/library/wyk4d9cy(v=vs.80).aspx

    也看過 http://zh.wikipedia.org/wiki/%E6%95%B8%E5%80%BC%E4%BF%AE%E7%B4%84%E8%A6%8F%E5%89%87

    但是下列程式碼輸出結果不如預期,是為什麼?

    Public Class Form1
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim s As Double
            Dim r As Double
            Dim re As Double
            Dim ra As Double
            For i As Integer = 0 To 3000 Step 1
                s = i / 10000 + 0.00005
                r = Math.Round(s, 4)
                re = Math.Round(s, 4, MidpointRounding.ToEven)
                ra = Math.Round(s, 4, MidpointRounding.AwayFromZero)
                Debug.Print(s & " : " & r & IIf(r > s, ",O", ",X") & "," & re & IIf(re > s, ",O", ",X") & "," & ra & IIf(ra > s, ",O", ",X"))
            Next
        End Sub
    End Class

    輸出結果

    0.00015 : 0.0002,O,0.0002,O,0.0002,O
    0.00025 : 0.0002,X,0.0002,X,0.0003,O
    0.00035 : 0.0004,O,0.0004,O,0.0004,O
    0.00045 : 0.0004,X,0.0004,X,0.0005,O
    0.00055 : 0.0006,O,0.0006,O,0.0006,O
    0.00065 : 0.0006,X,0.0006,X,0.0007,O
    0.00075 : 0.0008,O,0.0008,O,0.0008,O
    0.00085 : 0.0008,X,0.0008,X,0.0009,O
    0.00095 : 0.001,O,0.001,O,0.001,O
    0.00105 : 0.001,X,0.001,X,0.0011,O
    0.00115 : 0.0012,O,0.0012,O,0.0012,O
    0.00125 : 0.0012,X,0.0012,X,0.0012,X<-這第三組為什麼沒進位
    0.00135 : 0.0013,X,0.0013,X,0.0013,X<-奇數不是應該進位
    0.00145 : 0.0014,X,0.0014,X,0.0014,X<-這第三組為什麼沒進位
    0.00155 : 0.0016,O,0.0016,O,0.0016,O
    0.00165 : 0.0016,X,0.0016,X,0.0017,O
    0.00175 : 0.0017,X,0.0017,X,0.0017,X<-奇數不是應該進位
    0.00185 : 0.0018,X,0.0018,X,0.0019,O
    0.00195 : 0.002,O,0.002,O,0.002,O
    0.00205 : 0.002,X,0.002,X,0.0021,O<-
    0.00215 : 0.0022,O,0.0022,O,0.0022,O
    0.00225 : 0.0023,O,0.0023,O,0.0023,O<-
    0.00235 : 0.0024,O,0.0024,O,0.0024,O

    -----------------------------------------------------------------------------------------

    0.00015 : 0.0002,O,0.0002,O,0.0002,O
    0.00115 : 0.0012,O,0.0012,O,0.0012,O
    0.00215 : 0.0022,O,0.0022,O,0.0022,O
    0.00315 : 0.0032,O,0.0032,O,0.0032,O
    0.00415 : 0.0042,O,0.0042,O,0.0042,O
    0.00515 : 0.0052,O,0.0052,O,0.0052,O
    0.00615 : 0.0062,O,0.0062,O,0.0062,O
    0.00715 : 0.0072,O,0.0072,O,0.0072,O

    0.00815 : 0.0081,X,0.0081,X,0.0081,X <-為什麼這不進位

    -----------------------------------------------------------------------------------------

    0.00025 : 0.0002,X,0.0002,X,0.0003,O
    0.00125 : 0.0012,X,0.0012,X,0.0012,X
    0.00225 : 0.0023,O,0.0023,O,0.0023,O
    0.00325 : 0.0032,X,0.0032,X,0.0033,O
    0.00425 : 0.0042,X,0.0042,X,0.0042,X
    0.00525 : 0.0052,X,0.0052,X,0.0052,X
    0.00625 : 0.0062,X,0.0062,X,0.0062,X
    0.00725 : 0.0072,X,0.0072,X,0.0073,O
    0.00825 : 0.0082,X,0.0082,X,0.0083,O
    0.00925 : 0.0092,X,0.0092,X,0.0093,O
    0.01025 : 0.0102,X,0.0102,X,0.0103,O

    0.01125 : 0.0112,X,0.0112,X,0.0113,O

    越後面越不知道規則在哪裡,有人可以解釋一下嗎?不太懂實際的結果為什麼會這樣!!


    chansetter


    一句話點醒我夢中人........
    • 已編輯 黑_ 2013年3月26日 上午 09:22
    2013年3月26日 上午 09:08

解答

所有回覆

  • 您好,

    因為double是非精準數值,所以Round時,會先轉成10進位,然後再來處理Round。所以因此造成該進位而沒進位的狀況。

    請參考:Math.Round(decimal, Int32) 與 Math.Round(Double, Int32)


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/


    • 已提議為解答 Alex_Lee 2013年3月26日 上午 09:19
    • 已編輯 亂馬客 2013年3月26日 上午 09:21
    • 已標示為解答 黑_ 2013年3月26日 上午 09:21
    2013年3月26日 上午 09:18
  • 一句話點醒我夢中人........

    非常感謝,原來這麼簡單,突然覺得我好蠢


    chansetter

    2013年3月26日 上午 09:23
  • 是正确的:

    规则:

    1)保留N位,那么AwayFromZero规则:

    1.1)如果后一位大于5,直接进位。

    1.2)如果后一位小于5,直接舍去。

    1.3)如果后一位=5,后面如果还有数字,直接进位1.

    1.4)后一位=5,后面没有任何数字,那么前一位是偶数,直接舍去;否则进位凑成偶数。

    0.00125,保留4位,那么按照这个规则:

    第五位为5,后面没有任何数字,且第四位为偶数,直接舍去(0.0012)。

    我用控制台运行,完全正确。

    Module Module1
        Sub Main()
            Dim s As Double
            Dim r As Double
            Dim re As Double
            Dim ra As Double
            For i As Integer = 0 To 100
                s = i / 10000 + 0.00005
                r = Math.Round(s4)
                re = Math.Round(s4MidpointRounding.ToEven)
                ra = Math.Round(s4MidpointRounding.AwayFromZero)
                Console.WriteLine(s & " : " & r & IIf(r > s",O"",X") & "," & re & IIf(re > s",O"",X") & "," & ra & IIf(ra > s",O"",X"))
            Next
        End Sub
    End Module

    If you think one reply solves your problem, please mark it as An Answer, if you think someone's reply helps you, please mark it as a Proposed Answer

    Help by clicking:
    Click here to donate your rice to the poor
    Click to Donate
    Click to feed Dogs & Cats

    2013年3月26日 上午 09:25