15
int i = 0, j = 0;
double nan1 = (double)0/0;
double nan2 = (double)0/0;
double nan3 = (double)i/j;
System.out.println(Double.doubleToRawLongBits(nan1) == Double.doubleToRawLongBits(nan2));
System.out.println(Double.doubleToRawLongBits(nan1) == Double.doubleToRawLongBits((double)0/0));
System.out.println(Double.doubleToRawLongBits(nan3) == Double.doubleToRawLongBits(nan2));

出力:

true
true
false

true最初の 2falseつと最後の 1つの出力がどのように得られたか教えてください。Double.doubleToRawLongBits()メソッドの実際の動作を教えてください。

4

4 に答える 4

3

次のコードを実行して、値を確認してください。

public class Test
{
    public static void main(String[] args){
        int i = 0, j = 0;
        double nan1 = (double)0/0;
        double nan2 = (double)0/0;
        double nan3 = (double)i/j;
        System.out.println(Double.doubleToRawLongBits(nan1) + " == "+ Double.doubleToRawLongBits(nan2) + " is " +
            (Double.doubleToRawLongBits(nan1) == Double.doubleToRawLongBits(nan2)));
        System.out.println(Double.doubleToRawLongBits(nan1) + " == "+ Double.doubleToRawLongBits((double)0/0) + " is " +
            (Double.doubleToRawLongBits(nan1) == Double.doubleToRawLongBits((double)0/0)));
        System.out.println(Double.doubleToRawLongBits(nan3) + " == "+ Double.doubleToRawLongBits(nan2) + " is " +
            (Double.doubleToRawLongBits(nan3) == Double.doubleToRawLongBits(nan2)));
    }
}

私の Mac では、次の出力が生成されます。

9221120237041090560 == 9221120237041090560 is true
9221120237041090560 == 9221120237041090560 is true
-2251799813685248 == 9221120237041090560 is false

この落とし穴は、doubleToRawLongBits メソッドの Javadoc に記載されています。

引数が NaN の場合、結果は実際の NaN 値を表す倍長整数になります。doubleToLongBits メソッドとは異なり、doubleToRawLongBits は、NaN をエンコードするすべてのビット パターンを単一の「標準的な」NaN 値に集約しません。

于 2012-06-13T05:49:10.587 に答える
2

その理由は、double変数0を0で除算すると、NaNが返されるため、メソッドにはバイナリの単一の正規表現がないため、NaNのバイナリが7F F8 00 00 00 000000またはFFF800として返される可能性があるためです。 00 00 000000。

技術的には同じもの、つまりNaNを表しますが、バイナリ表現が異なります。

于 2012-06-13T06:01:03.550 に答える
2

IEEE 754 標準では、さまざまなビット パターンを使用できますNaN。計算と比較の目的では、それらはすべて同じように機能する必要があります (つまり、NaN比較はそれ自体と等しくなく、順序付けられておらず、関連するすべての計算NaNNaNそれ自体です)。使用doubleToRawLongBitsされている正確なビットパターンを取得します。これは JLS でも詳しく説明されています。

ほとんどの場合、Java プラットフォームは、指定された型の NaN 値を単一の正規値にまとめられたかのように扱います (したがって、この仕様は通常、任意の NaN を正規値であるかのように参照します)。Float.floatToRawIntBitsただし、バージョン 1.3 の Java プラットフォームでは、プログラマーが NaN 値を区別できるようにするメソッドが導入されましたDouble.double- ToRawLongBitsFloat詳細については、およびクラスの仕様を参照してDoubleください。

あなたの場合、符号ビットが異なります。この場合、ウィキペディアに誘導できます。ウィキペディアはこれを簡潔にまとめています。

IEEE 754 標準準拠の浮動小数点ストレージ形式では、NaN は、NaN に固有の特定の定義済みビット パターンによって識別されます。符号ビットは関係ありません。

両方の値はNaNです。異なるビットを使用してそれを表しています。IEEE 754 で許可されているものであり、この場合、実際のハードウェアが別の結果を返す一方で、コンパイラDouble.NaNが一定の計算を代用していることに起因する可能性があります。NaN

于 2012-06-13T06:07:29.853 に答える
1

Java は IEEE 754 に従っていると思います。この場合、NaN には複数の可能なビット表現があります。あなたの場合の2つの表現は、「符号」ビットが異なります。符号ビットの値は標準で定義されていないようで、通常は無視されます。したがって、両方の値は正しいです。http://en.wikipedia.org/wiki/NaNを参照

于 2012-06-13T05:58:23.507 に答える