小数値の丸めは Math.Round メソッドを利用するのがわかりやすいです。
Math.Round(d, decimals, mode)
d : 数値
decimals : 丸め位置
mode : 丸め方法
ポイントは、丸め方法 Mode です。
丸め方法のModeパラメータは、System.MidpointRounding 列挙体の ToEven or AwayFromZero 引数をとります。
丸め方法の動作は IEEE 規格 754、セクション 4 に従っているので、ISO JIS などもフォロー。 1
Round メソッドを利用する場合には、ToEven と AwayFromZero が丸め方法のうち、何になるのかを理解する必要があります。 JIS8401 規則だと、次のようになっていることを、知るということです。
- ToEven = JIS 8401 規則A
- AwayFromZero = JIS 8401 規則B
丸め方の違いを確認する
規則Aと規則Bで丸める挙動が異なるのは、次のケースです。 与えられた数値に等しく近い、2つの隣り合う数値がある場合に挙動が異なります。
例)
数値:10.2345(小数第3位で丸める)
ToEven = 10.234
AwayFromZero = 10.235
var value = 10.2345; var r1 = Math.Round(value, RoundPos, MidpointRounding.ToEven); // 規則A var r2 = Math.Round(value, RoundPos, MidpointRounding.AwayFromZero); // 規則B
Excel の挙動
エクセル(2013)のRoundの挙動についても言及しておきます。 これは情報が多いですが、セル上での計算と、VBAでの結果が異なっているようです。
- セル = JIS 8401 規則B
- VBA = JIS 8401 規則A
図のとおり、セル上で =ROUND() で計算した値と、VBA の計算結果が一致しません。
計算誤差に関する問い合わせの多くは、日本だと「Excel で計算したんだけど」から、始まるケースが多いですが、丸め方がそもそも違っていることが少なくないです。
あらかじめ、丸め方の宣言書を提出しておくケースもあります。
サンプルプログラム
小数点以下の丸め方の差を比較するサンプルを公開しています。
「DecimalValueRoundTest」プロジェクトです。
参考
- Microsoft Docs - Math.Round Method
- IEEE - 754-2008 Standard for Floating-Point Arithmetic
- wiki - IEEE 754
- 作者:Bill Wagner
- 発売日: 2018/09/05
- メディア: 単行本(ソフトカバー)
-
It conforms to IEEE Standard 754, section 4. (Docs - Math.Round Method)↩