web-dev-qa-db-ja.com

System.Doubleを '0'(数値、int?)と比較する正しい方法

申し訳ありませんが、これは簡単な愚かな質問かもしれませんが、確実に知る必要があります。

このif式がありますが、

void Foo()
{
    System.Double something = GetSomething();
    if (something == 0) //Comparison of floating point numbers with equality 
                     // operator. Possible loss of precision while rounding value
        {}
}

その式は等しいですか

void Foo()
{
    System.Double something = GetSomething();
    if (something < 1)
        {}
}

?私は問題があるかもしれないので、例えばifを入力します0.9の値。

80
radbyx

それでは、値を0に近づける必要がありますか? 「無限精度」で結果が0になる可能性がある多くの浮動小数点演算を実行すると、結果が「非常に近い」0になる可能性があります。

通常、この状況では、何らかのイプシロンを提供し、結果がそのイプシロン内にあることを確認します。

if (Math.Abs(something) < 0.001)

使用するイプシロンはアプリケーション固有です-何をしているのかに依存します。

もちろん、結果がexactly 0である場合、単純な等価性チェックで問題ありません。

100
Jon Skeet

somethingsomething = 0以外の操作の結果から割り当てられている場合は、以下を使用する方が適切です。

if(Math.Abs(something) < Double.Epsilon)
{
//do something
}

編集:このコードは間違っています。イプシロンは最小の数字ですが、ゼロではありません。ある数値を別の数値と比較したい場合、許容できる許容範囲を考える必要があります。 .00001を超えるものは気にしないとしましょう。それがあなたが使う数字です。値はドメインによって異なります。ただし、Double.Epsilonはほとんどありません。

29
sonatique

あなたのsomethingdoubleであり、行でそれを正しく識別しました

if (something == 0)

左側にdouble(lhs)と右側にintがあります(rhs)。

しかし、今ではlhsはintに変換され、==記号は2つの整数を比較します。それはnot何が起こるかです。変換fromdoubletointexplicitであり、「自動的に」発生することはありません。

代わりに、反対のことが起こります。 rhsはdoubleに変換され、次に==符号は、2つのdouble間の等価性テストになります。この変換は暗黙的(自動)です。

書く方が良いと考えられています

if (something == 0.0)

または

if (something == 0d)

なぜなら、2つのdoubleを比較しているのはすぐにわかるからです。ただし、コンパイラはどのような場合でも同じことを行うため、スタイルと読みやすさの問題です。

場合によっては、ジョンスキートの答えのように「トレランス」を導入することも重要ですが、そのトレランスもdoubleになります。それcouldもちろん1.0必要に応じて、ただし[厳密に正の最小]整数である必要はありません。

19

警告を単に抑制したい場合は、これを実行します。

if (something.Equals(0.0))

もちろん、これはドリフトが問題ではないことがわかっている場合にのみ有効なソリューションです。ゼロで除算しようとしているかどうかを確認するために頻繁にこれを行います。

15

正直言って、平等だとは思わない。あなた自身の例を考えてみましょう:何か= 0.9、または0.0004。最初の場合はFALSE、2番目の場合はTRUEです。このタイプに対処するには、通常、精度のパーセンテージを定義し、その精度内で比較します。ニーズに依存します。何かのようなもの...

if(((int)(something*100)) == 0) {


//do something
}

お役に立てれば。

4
Tigran

ここに問題を提示する例があります(LinQPadで準備-持っていない場合は、単にConsole.Writeline代わりにDumpメソッド):

void Main()
{
    double x = 0.000001 / 0.1;
    double y = 0.001 * 0.01; 

    double res = (x-y);
    res.Dump();
    (res == 0).Dump();
}

Xとyは両方とも理論的には同じであり、0.00001に等しいが、「無限精度」がないため、これらの値はわずかに異なる。残念ながら、通常の方法で0と比較したときにfalseを返すのに十分なだけです。

2