39

私は、SQL Decimal (38,30) に由来する C# の 10 進数の精度と戦ってきました。ここで明らかなことを見落としている可能性があることはわかっていますが、少し洞察が必要です。

私が抱えている問題は、C# が一貫した出力と見なすものを生成しないことです。

decimal a = 0.387518769125m;
decimal b = 0.3875187691250002636113061835m;

Console.WriteLine(Math.Round(a, 11));
Console.WriteLine(Math.Round(b, 11));
Console.WriteLine(Math.Round(a, 11) == Math.Round(b, 11));

収量

0.38751876912
0.38751876913
False

ええと、0.38751876913? 本当に?ここで何が欠けていますか?

MSDNから:

小数点以下の桁が奇数の場合、偶数桁に変更されます。それ以外の場合は変更されません。

一貫性のない結果が表示されるのはなぜですか? 追加の精度は、「小数点以下の桁数」を変更していません...

4

4 に答える 4

47

MSDN から:

ddecimals小数点以下の右側0 以外の数字が 1 つあり、その値が5の場合、小数点以下の桁が奇数の場合は切り上げられ、偶数の場合は変更されませんdの小数桁数が よりも少ない場合decimalsdは変更されずに返されます。

あなたの最初のケースでは

decimal a = 0.387518769125m;
Console.WriteLine(Math.Round(a, 11));

11 位の右に 1 桁あり、その数字は5です。したがって、位置 11 は偶数であるため、変更されません。したがって、あなたは得る

0.38751876912

あなたの2番目のケースでは

decimal b = 0.3875187691250002636113061835m;
Console.WriteLine(Math.Round(b, 11));

11 位の右に 1 桁の数字がありません。したがって、これは小学校の丸めです。次の桁が 4 より大きい場合は切り上げ、それ以外の場合は切り捨てます。11位の右の桁が4より大きいので(5です)切り上げます

0.38751876913

一貫性のない結果が表示されるのはなぜですか?

あなたではない。結果はドキュメントと完全に一致しています。

于 2012-04-12T16:13:23.103 に答える
26

MSDN から - Math.Round メソッド (10 進数、Int32) :

d の小数点以下の桁の右側に 0 以外の数字が 1 つあり、その値が 5 の場合、小数点以下の桁が奇数の場合は切り上げられ、偶数の場合は変更されません。d の小数部の桁数が 10 進数よりも少ない場合、d は変更されずに返されます。

このメソッドの動作は、IEEE 規格 754 のセクション 4 に従います。中間値を一方向に一貫して丸めることに起因する丸め誤差を最小限に抑えます。

単一のゼロ以外の数字の使用に注意してください。これは最初の例に対応していますが、2 番目の例には対応していません

と:

Round(Decimal, Int32) メソッドで使用される丸めの種類を制御するには、Decimal.Round(Decimal, Int32, MidpointRounding) オーバーロードを呼び出します。

于 2012-04-12T16:10:34.170 に答える
4

「小数点以下の桁数の右側にある d の 0 以外の 1 桁で、その値は 5 です」という部分が結果を説明しています。丸める部分が正確に 0.5 の場合にのみ、丸めルールが適用されます。

于 2012-04-12T16:12:23.997 に答える