2011-08-24 6 views
24

私は次のコードを持っています:平等のための二重チェックは今まで安全でしたか?

double x = 0; 

{ ...do stuff ...} 

if(x == 0){ 

} 

私は常に浮動小数点数をチェックしてはならないと教えていました。ゼロと等しいかどうかをチェックしていますか?

+0

init xを0にした場合、0であることを確認できないのはなぜですか? 0はdoubleの有効な値です – JohnJohnGa

+1

限界に達すると浮動小数点数の丸めが大きくなります。同じ理由で、基数10で使用する3桁の数字がある場合、.004を持ち、3で割ると、.001が出ますが、何が起こるかは分かります。 –

+0

トーマスの訂正:これは技術的には四捨五入ではありませんが、浮動小数点の精度とバイナリ性が限られているため不正確です。 –

答えて

27

浮動小数点数が等しいかどうかチェックするべきではない理由は、浮動小数点数が完全に正確ではないことです。仮数部にあまりにも遠すぎて小数点を繰り返したような、私は基数2の小数点以下の繰り返しについて話しています)。この不正確さは「切り捨て」と考えることができます。浮動小数点数の精度を超える桁は切り捨てられ、実質的に切り捨てられます。

変更されていない場合は、その同等性が維持されます。しかし、少しでもそれを変更した場合は、等価を使用するのではなく、(x < 0.0001 && x > -.0001)のような範囲を使うべきです。

要するに、あなたが非常に小さなレベルでxで遊んでいない限り、それは問題ありません。

+6

浮動小数点数の表現のために特定の数値を格納することができません。 0は浮動小数点値で正確に表現できますが、すべての値がそうであるわけではありません。例えば、0.1を近似しなければならない。 –

+1

@トーマスラウンドダウン。 '3/2'が' 1'と同じ理由 –

+7

いいえ、丸められません。 IEEE浮動小数点表記における不正確さ。丸めとはまったく関係ありません。 http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems –

16

キャッチしようとしている0が初期化時に元の0に設定されていれば安全です。しかし、数学的操作から0を期待している場合は安全ではありません。

+0

数学操作の0を比較したいときには、適切なアプローチが必要です。 –

+0

受け入れられた答えを見てください。 – Vache

4

まだゼロに等しいかどうかを確認するべきではありません。それがゼロに近いかどうかを確認するだけです。

private final static double EPSILON = 0.00001; 
if (x + EPSILON > 0 && x - EPSILON < 0){ 
... 
} 
+3

絶対的なエピソードではなく、相対的なエピソードを使うべきです。もし値が広い範囲にわたって変化することができるならば、これは特に当てはまります。 –

+2

@HovercraftFullOfEelsこれは、ターゲットが肯定的な場合にのみ機能します。 –

4

あなたはそれを自分で設定し、それは今まであなたが安全に(センチネル値を使用してのような)の等価性をチェックすることができます変更かどうかを確認したい場合はNaNがその

float x=Float.NaN; 
{ 
    //some code that may or may not set x 
} 
if(Float.isNaN(x))//it never got set 
2

のようなもののために安全であるものの、二重あり正と負のゼロ。正のゼロと負のゼロの間の==はfalseを返します。また、2つのNaN間の==はfalseを返します。

関連する問題