質問: (double)Math.Round((decimal)test1, 11, MidpointRounding.AwayFromZero); ※test2の値はdouble型で316.22618487406になりました。 IEEE754準拠とdouble特有の誤差、銀行型の丸めという3つの要素があるとのことで、406を期待した理由から考え直して予想してみました。 MS-DOSの時代にコンパイルされたEXEの計算挙動を調べていたというのが「C#の四捨五入がなぜ違うのか」と思った原因でもありました。 そのEXEは数値の扱いがdouble型の挙動でしたが計算式の結果値を64ビットよりも少ない有効桁数に丸める特徴(仕様)があったので、計算式中と結果値の桁数をそれぞれ調べていたところ SQRT(99999)が316.22618487406 と表示されるので丸め方を予測していたところ、どうしても11桁での四捨五入で最後の4055の5が繰り上がっているとしか思えなかったのです。 丸め方がCPUにdoubleを扱わせるのとは関係ないのであれば、当時は丸め方の方針そのものがコンパイラメーカー又はEXEを作った人の独自実装だったのかもしれないので、IEEE754や銀行型丸めでもなく、一般的な四捨五入となるように実装されていたのかもしれません。(double型特有の誤差を無くしての四捨五入を実装する方が、逆に大変そうですが・・・)
回答: `double` の表現精度は15桁で、`316.226184874055`は15桁なので保持する数値を内部的に(内部的には17桁ある)正しく表現できていないのではないかと思います。 このような場合(数の表現桁数が限度に近い場合、浮動小数の表現に正確性を求められる場合)には、decimal型を使うのがいいかと思います。 例: `Math.Round(316.226184874055m, 11);`//=>316.22618487406