[C#]四捨五入するときに注意すべき銀行型丸め(最近接偶数への丸め)について


C#の四捨五入の規定値は「銀行型丸め(または最近接偶数への丸め)」です。
注意しないと思わぬところでハマります。



C#で数値を四捨五入するときMath.Roundメソッドを使うと思います。
ただ、何も考えずに

var value = 2.5m;
var dest = Math.Round(value);

なんてすると思いもよらぬ結果を招きます
上の例だと、求めた結果が「3.0」ではなく「2.0」になります。

これは、Math.Roundメソッドの四捨五入の形式が「銀行型丸め(または最近接偶数への丸め)」の為です。
銀行型丸め(または最近接偶数への丸め)についての解説はWikipedia等にありますのでそちらを参照していただければと。

では、普通に考える「3.0」を結果として求めるにはどうすればよいかと言うと、Math.Roundメソッドの第2引数に
「MidpointRounding.AwayFromZero」
を指定すれば良いです。

var value = 2.5m;
var dest = Math.Round(value, MidpointRounding.AwayFromZero);

これで、求めた結果が「3.0」になります。

・参考
MSDNライブラリ Math.Round(Decimal, MidpointRounding)
MSDNライブラリ MidpointRounding 列挙体

銀行型丸めと普通の丸めを行った際の実行結果です。

for (var source = 1.0m; source <= 3.0m; source += 0.1m)
{
    var dest = Math.Round(source);
    var dest2 = Math.Round(source, MidpointRounding.AwayFromZero);
    System.Diagnostics.Debug.WriteLine("{0} -> {1} | {2}", source, dest, dest2);
}

結果

1.0 -> 1 | 1
1.1 -> 1 | 1
1.2 -> 1 | 1
1.3 -> 1 | 1
1.4 -> 1 | 1
1.5 -> 2 | 2
1.6 -> 2 | 2
1.7 -> 2 | 2
1.8 -> 2 | 2
1.9 -> 2 | 2
2.0 -> 2 | 2
2.1 -> 2 | 2
2.2 -> 2 | 2
2.3 -> 2 | 2
2.4 -> 2 | 2
2.5 -> 2 | 3      ★ココ
2.6 -> 3 | 3
2.7 -> 3 | 3
2.8 -> 3 | 3
2.9 -> 3 | 3
3.0 -> 3 | 3

やっぱり「2.5」の部分が違います。
気をつけましょう。