Roundメソッドを使った正しい四捨五入の実装方法

C#の標準クラスではMath.Roundという数値の四捨五入に使えるメソッドがある。
docs.microsoft.com

このMath.Roundメソッドだがそのまま何も考えずに四捨五入で使うと問題が起きる。
例えば以下のようなケース。

Console.WriteLine(Math.Round(1.5));
Console.WriteLine(Math.Round(2.5));
Console.WriteLine(Math.Round(3.5));
Console.WriteLine(Math.Round(4.5));

Microsoftのページをよく読んでいないとすべて繰り上げされると思いがちだが、実際は以下のような結果になる。

2
2
4
4

2.5は四捨五入したら3、4.5は5で出力されてほしいが意図通りならない。
なぜこのような結果になるかというと、Math.Roundに第2引数を指定しない場合のデフォルトの動作は
「10 進数の値は最も近い整数値に丸められ、中間値は最も近い偶数値に丸められる」という仕様だからだ。
小学校の時に習った単純な四捨五入とは違う動作がデフォルトということだ。


これを正しく実装するには第2引数にMidpointRounding.AwayFromZeroを追加しメソッドを使う必要がある。

Console.WriteLine(Math.Round(1.5, MidpointRounding.AwayFromZero));
Console.WriteLine(Math.Round(2.5, MidpointRounding.AwayFromZero));
Console.WriteLine(Math.Round(3.5, MidpointRounding.AwayFromZero));
Console.WriteLine(Math.Round(4.5, MidpointRounding.AwayFromZero));

これで実装すると以下のように全て繰り上げて処理される。

2
3
4
5