2012-08-24 14 views
18

なぜそれは私が次の操作を実行したときにということで小数点以下2桁に丸めは...私は0.8</p> <p>が、私は次の操作を行い得る...

Math.Round(0.575, 2, MidpointRounding.AwayFromZero) 

Math.Round(0.75, 1, MidpointRounding.AwayFromZero) 

お困り

私は0.58を得ません。代わりに私は0.57を得る。 5倍以上の値を切り上げたいので、0.575は0.58にする必要があります。

+0

[この質問の最初の回答](http://stackoverflow.com/q/5641616/62576)がこの回答に役立ちます。 –

+0

@KenWhite:それは確信しています。問題は、実際の数学が '.575'をゼロから2桁小数点以下に丸めると' .58 'が出るが、これは観測結果ではないという問題がある。この場合、浮動小数点表記と関係がある。 – Chris

+0

@Chris:そうです。 :-)私は主にDelphiを使用しています。Round()は、このような処理を大部分はうまく処理します。私はちょうどC#でチェックして、問題を見ることができます。 –

答えて

30

問題は、0.575を正確に2進浮動小数点数(doubleなど)で表すことができないことになります。私はちょうどそれが最も近い表現はちょうど少し低いと思われることを正確にはわからないが、それを丸めるときには真の表現を使用して切り捨てる。

この問題を回避するには、より適切なデータ型を使用します。 decimalはあなたがやりたいことになります。

Math.Round(0.575M, 2, MidpointRounding.AwayFromZero) 

結果:0.58

0.75が正しいことがないという理由は、簡単であるため2進浮動小数点で表現するために簡単なことです

1/2 + 1/4(すなわち、2^-1 + 2^-2)である。一般に、2のべき乗の任意の有限和は、2進浮動小数点で表現することができる。例外は、2の威力が大きすぎる範囲(例えば、2^100 + 2が正確に表現できない場合)です。

編集、追加する:

Formatting doubles for output in C#は0.575が本当に0.575ではないことを理解し、なぜその一生懸命理解するという点で関心があるかもしれません。受け入れられた答えのDoubleConverterは、正確な文字列として0.575が0.5749999999999999555910790149937383830547332763671875であることを示します。丸めが0.57を与える理由は、これから分かります。

+2

すべての情報をお寄せいただきありがとうございます。私は二重に10進数に切り替えると、そのトリックを行います。ありがとう! –

2

倍精度/小数点以下の精度が不足していることが原因です(つまり、関数はには常にの結果が得られません)。そのため、浮動小数点数として小数値を表すか、フローティングに算術演算を実行することから生じ得る精度の損失の

:ここ

MSDN on Math.Roundが関連の引用である:

は、次のリンクを参照してください。ポイント値の場合、Round(Double、Int32、MidpointRounding)メソッドは、modeパラメータで指定された中点値を丸めて表示されない場合があります。次の例では、2.135が2.14の代わりに2.13に丸められています内部的には、この方法では値に10digitsを乗算し、乗算opこの場合の侵食は精度の低下に悩まされる。

7

System.Math.Round方法は、小数点精度エラーを浮遊する傾向がある他の人が指摘しているように、Double構造を使用します。

Decimal.Round(0.575, 2, MidpointRounding.AwayFromZero) 

結果::私はそれは同じ問題に悩まされないと小数としてあなたの変数をredifining必要としないSystem.Decimal.Round方法を、使用していた遭遇したとき、この問題を見つけ、簡単な解決策I 0。58

関連する問題