VB2019 での Math.Round で四捨五入されないように見える件
VB2019 での Math.Round で四捨五入されないように見える件
VisualBasic (VisualStudio 2019, .NET Framework 4.7.2) の Math.Round()
関数で下のような挙動(中間値なのに切り上げられない)となる理由をご教示頂ければと思います。
※Decimal
型の利用で解決できる事は確認しております。後学のため、詳細な理由を教えて頂ければ幸いです。
※明示的に MidpointRounding.AwayFromZero
を指定しているので「銀行家丸め(ToEven
)」にはならないはず…
発生している問題・エラー
TestMathRound
ソース: SampleTest.vb 行 7
期間: 2 ミリ秒
メッセージ:
Assert.AreEqual に失敗しました。<8251.491110> が必要ですが、<8251.491100> が指定されました。
スタック トレース:
SampleTest.TestMathRound() 行 8
TestSample
ソース: SampleTest.vb 行 12
期間: < 1 ミリ秒
指定桁(5桁目)の次が「5」なので四捨五入されれば繰り上がるはずなのですが、切り捨てられてテストが失敗します。
(確認用に丸め桁(5)より 1桁多くToString("F6")
で出力しています)
数値が読み辛くて申し訳ありません
該当するソースコード
Imports System.Text
Imports Microsoft.VisualStudio.TestTools.UnitTesting
<TestClass>
Public Class SampleTest
<TestMethod>
Public Sub TestMathRound()
Assert.AreEqual("8251.491110", Math.Round(8251.491_105, 5, MidpointRounding.AwayFromZero).ToString("F6")) ' 四捨五入されない?
End Sub
<TestMethod>
Public Sub TestSample()
Dim target As Double = 0.008_251_491_105 * Math.Pow(10, 6)
Assert.AreEqual("8251.491105", target.ToString("R"))
Assert.AreEqual(False, target < 8251.491_105)
Assert.AreEqual(False, target > 8251.491_105)
End Sub
End Class
自分で試したこと
本来は TestSample()
内のように桁シフトしてから丸めていた時に気付きました。
(当然ですが)次のように少しだけ値を大きくするとテスト成功します。
- Math.Round(8251.491_105, 5, MidpointRounding.AwayFromZero)
+ Math.Round(8251.491_105_00001, 5, MidpointRounding.AwayFromZero)
TestSample()
で、ラウンドトリップ形式での表示も、リテラル値との比較結果も Double 特有の微小誤差の存在を示していない点が不可解です。
※Double の下位桁にゴミがあれば、ToString("R")
で表示されるはず…
単なる疑問の上、もしかしたら常識なのかもしれませんが、ご存知の方がおられましたらご協力いただけると嬉しいです。
よろしくお願いいたします。