1

この次の算術問題に遭遇しました。

しかし、結果は通常の演算とは異なります。

double d1 = 1.000001;

double d2 = 0.000001;

Console.WriteLine((d1-d2)==1.0);
4

9 に答える 9

14

Jon Skeet の Brainteasers ページで質問を見つけたと思いますか? 回答は、同じ Web サイトでここにリストされ、説明されています。

参考までに、そのページからコピーした回答を次に示します。


3) 愚かな算数

コンピュータは算数が得意なはずですよね。これが「False」と表示されるのはなぜですか?

double d1 = 1.000001; double d2 =
0.000001; Console.WriteLine((d1-d2)==1.0);

回答: ここにあるすべての値は、2 進浮動小数点として格納されます。While 1.0 can be stored exactly, 1.000001 is actually stored as 1.0000009999999999177333620536956004798412322998046875, and 0.000001 is actually stored as 0.000000999999999999999954748111825886258685613938723690807819366455078125. それらの差は正確に 1.0 ではなく、実際、差も正確に保存することはできません。


于 2009-04-06T11:15:39.787 に答える
3

Double.Equalsの MSDN エントリから:

比較の精度

Equals メソッドは注意して使用する必要があります。これは、2 つの値の精度が異なるため、2 つの明らかに同等の値が等しくない場合があるためです。次の例では、Double 値 .3333 と、1 を 3 で除算して返される Double が等しくないことを報告しています。

...

同等性を比較するのではなく、2 つの値の差の許容範囲を定義することを推奨する手法の 1 つです (値の 0.01% など)。2 つの値の差の絶対値がそのマージン以下である場合、その差は精度の差によるものである可能性が高く、したがって、値が等しい可能性があります。次の例では、この手法を使用して、前のコード例で等しくないことが判明した 2 つの Double 値である .33333 と 1/3 を比較しています。

多くの「等しい」比較を行う必要がある場合は、比較のために .NET 3.5 で小さなヘルパー関数または拡張メソッドを作成することをお勧めします。

public static bool AlmostEquals(this double double1, double double2, double precision)
{
    return (Math.Abs(double1 - double2) <= precision);
}

これは次のように使用できます。

double d1 = 1.000001;

double d2 = 0.000001;

bool equals = (d1 - d2).AlmostEquals(1.0, 0.0000001);

この非常によく似た質問を参照してください: C#.NET: Is it safe to check floating point values for equality to 0?

于 2009-04-06T11:19:13.727 に答える
2

これは、コンピューターが基数 2 で計算を行うため、限られた桁数では多くの 10 進浮動小数点数を正確に表すことができないためです。

于 2009-04-06T11:15:10.723 に答える
2

浮動小数点数を使用しているためです。

http://docs.sun.com/source/806-3568/ncg_goldberg.html

于 2009-04-06T11:16:42.967 に答える
2

アプリケーションでそのような演算を行う場合は、decimal型を使用する必要があります

decimal d1 = 1.000001M;

decimal d2 = 0.000001M;

Console.WriteLine((d1 - d2) == 1.0M); // evaluates as true
于 2009-04-06T11:25:37.907 に答える
1

これは、結果が正確に 1.0 ではなく、1.000000000001 のようなものである可能性があるため、浮動小数点の精度の問題が原因である可能性があります。

于 2009-04-06T11:15:35.997 に答える
1

これは、浮動小数点型が基数 10 表現ではなく基数 2 を使用して数値を格納するために発生します。これにより、 double は 0.1 のような値を正確に格納できないという結果になります。たとえば、0.1 は単一の値 0.100000001490116119384765625 で表されます。

エラーを取り除くには Decimal を使用する必要があります。

于 2009-04-06T11:15:57.070 に答える
1

これは、浮動小数点数が CPU で機能する方法によるもので、C# 固有のものではありません。詳細については、このウィキペディアのエントリと論文を参照してください。

簡単な答えは、浮動小数点数は正確な表現として保存されないため、「==」を使用して比較を行うと、使用しようとしている方法では機能しないということです。

于 2009-04-06T11:18:15.100 に答える
0

問題は両方で同じであると言われているPythonドキュメントを参照してください。

http://docs.python.org/tutorial/floatingpoint.html

于 2009-04-06T11:17:02.327 に答える