7

2 つの double を追加しているときに、いくつかの奇妙な動作に気付きました。正しく動作する場合とそうでない場合があります。

最初の例を次に示します。

double num1 = 0.1 + 0.7; //Guess the result?

簡単 - 0.8 !!! か否か?

奇妙な結果を見てください:

ここに画像の説明を入力

if ステートメントは else ブロック内にあり、num1- を出力しますが、いいえ、0.799999999999993 を出力せず、0.8 を出力します。

だから私はもう一歩進んで、このコードを試しました:

if (0.1 + 0.7 == 0.8) //Returns false ??
{
    Console.WriteLine("Correct");
}

OK、奇妙ですが、正しい方法を見つけました。 f (float) を使用する必要があります。double には多くのスペースが含まれていることを覚えているので、より大きな数値を含めることができます。これが原因かもしれません。

float num2 = 0.1f + 0.7f;

if (num2 == 0.8f) //Perfect - finally works !!!
{
    Console.WriteLine("Correct");
}
else
{
    Console.WriteLine(num2);
}

しかし今、私はこれを試してみました - そして再び false を返します、なぜですか?

if (0.1f + 0.7f == 0.8f) //Returns false :(
{
    Console.WriteLine("Correct");
}

デバッグ時のウォッチの結果は次のとおりです。

ここに画像の説明を入力

誰かがここで何が悪いのか説明できますか? それらはバグですか?

前もって感謝します。

4

4 に答える 4

8

浮動小数点演算は正確ではありません。記事What Every Computer Scientist Should Know About Floating-Point Arithmeticをお読みください。計算を 10 進数で正確にしたい場合は、 is という型を使用する必要がありdecimalます。基数が 2 ではなく 10 であることを除いて、 はおよび と同様に浮動小数点数を使用することに注意してください。また、独自の不正確さもあります。10 進数の短い桁数 (や など) で表現できる数値を扱う場合にのみ正確であり、財務データに適しています。0.1m + 0.7m == 0.8mtruedecimalfloatdoubledecimal0.70.1

浮動小数点数を理解するのに役立つもう 1 つの記事は、ウィキペディアの倍精度浮動小数点形式です

于 2013-10-26T13:05:52.363 に答える
2

内部では、double は基数 2 のビット単位で格納されます。すべての整数は基数 2 で正確に表すことができますが、分数になると、まったく別の問題になります。

10 進法で 1/3 の結果を正確に表すことができないのと同じように、2 進法ではすべての分数を表すことはできません。10 進数は 10 進数なので、x/10 を 10 進数で表すのは簡単ですが、2 進数では一部の x では表せません。

したがって、double を使用するときは常に、丸め誤差に注意してください。

このため、金額のように正確な数値が必要な場合は常に double を使用しないでください。

于 2013-10-26T13:08:49.177 に答える
1

Math.Round メソッドを呼び出して、両方の値が同じ精度になるようにします。次の例では、前の例を変更してこのアプローチを使用し、2 つの小数値が同等になるようにします。

using System;

public class Example
{
   public static void Main()
   {
      double value1 = .333333333333333;
      double value2 = 1.0/3;
      int precision = 7;
      value1 = Math.Round(value1, precision);
      value2 = Math.Round(value2, precision);
      Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2));
   }
}
// The example displays the following output: 
//        0.3333333 = 0.3333333: True
于 2013-10-26T13:09:21.850 に答える
1

ここに答えがあります:http://www.codeproject.com/Articles/383871/Demystify-Csharp-floating-point-equality-and-relat

浮動小数点値は概算にすぎません。2 つの浮動小数点値を比較するには、それらの違いを確認する必要があります。差を超えることはできませんfloat.Epsilon

これを使用して、これらの値を比較します。

bool AlmostEqualDoubles(double nVal1, double nVal2, int nPrecision = 6)
{
   nPrecision = Math.Max(Math.Min(16, nPrecision), 0);
   double nEpsilon = 1.0;
   for (int i = 0; i < nPrecision; i++) nEpsilon *= 0.1;       
   return (nVal2 - nEpsilon) < nVal1 && nVal1 < (nVal2 + nEpsilon);
}
于 2013-10-26T13:13:03.310 に答える