159

OCPJP の質問を調べていたところ、次の奇妙なコードを見つけました。

public static void main(String a[]) {
    System.out.println(Double.NaN==Double.NaN);
    System.out.println(Double.NaN!=Double.NaN);
}

コードを実行すると、次のようになりました。

false
true

false互いに同じように見える 2 つのものを比較すると、出力はどうなりますか? とはNaNどういう意味ですか?

4

10 に答える 10

139

NaN は「非数」を意味します。

Java 言語仕様 (JLS) 第 3 版は次のように述べています

オーバーフローする演算は符号付き無限大を生成し、アンダーフローする演算は非正規化値または符号付きゼロを生成し、数学的に明確な結果を持たない演算は NaN を生成します。オペランドとして NaN を使用するすべての数値演算は、結果として NaN を生成します。すでに説明したように、NaN は順序付けされていないため、1 つまたは 2 つの NaN を含む数値比較演算は を返しfalse、 NaN を含む比較演算は を返します。!=truex!=xx

于 2012-01-11T13:06:06.800 に答える
62

NaN は、定義上、NaN を含む任意の数と等しくありません。これは IEEE 754 標準の一部であり、CPU/FPU によって実装されます。これは、JVM がサポートするロジックを追加する必要があるものではありません。

http://en.wikipedia.org/wiki/NaN

NaN との比較は、それ自体との比較であっても、常に順不同の結果を返します。... 等式および不等式の述語は非シグナリングであるため、x = x が false を返すことを使用して、x が quiet NaN であるかどうかをテストできます。

Java はすべての NaN を quiet NaN として扱います。

于 2012-01-11T14:04:35.377 に答える
51

なぜそのロジック

NaNを意味しNot a Numberます。数ではないものは何ですか? なんでも。片側に何かを持ち、反対側に何かを持つことができるので、両方が等しいことを保証するものは何もありません. のドキュメントでわかるように、 でNaN計算されます。Double.longBitsToDouble(0x7ff8000000000000L)longBitsToDouble

引数が ~ の範囲または ~ の範囲の任意の値である場合 、0x7ff0000000000001L結果 は.0x7fffffffffffffffL0xfff0000000000001L0xffffffffffffffffLNaN

また、NaNAPI 内で論理的に処理されます。


ドキュメンテーション

/** 
 * A constant holding a Not-a-Number (NaN) value of type
 * {@code double}. It is equivalent to the value returned by
 * {@code Double.longBitsToDouble(0x7ff8000000000000L)}.
 */
public static final double NaN = 0.0d / 0.0;

ちなみに、コードサンプルNaN としてテストされています:

/**
 * Returns {@code true} if the specified number is a
 * Not-a-Number (NaN) value, {@code false} otherwise.
 *
 * @param   v   the value to be tested.
 * @return  {@code true} if the value of the argument is NaN;
 *          {@code false} otherwise.
 */
static public boolean isNaN(double v) {
    return (v != v);
}

解決

あなたができることはcompare/を使うことですcompareTo

Double.NaNこのメソッドでは、 はそれ自体と等しく、他のすべてのdouble値 ( を含む Double.POSITIVE_INFINITY) よりも大きいと見なされます。

Double.compare(Double.NaN, Double.NaN);
Double.NaN.compareTo(Double.NaN);

または、equals:

thisargumentの両方が を表す場合Double.NaNequalsメソッドは値を持っていてtrueも を返します。Double.NaN==Double.NaNfalse

Double.NaN.equals(Double.NaN);
于 2012-01-11T13:35:15.610 に答える
6

Double.NaNのjavadocはそれをすべて言います:

type の非数 (NaN) 値を保持する定数double。によって返される値と同等Double.longBitsToDouble(0x7ff8000000000000L)です。

興味深いことに、 のソースでは次のようにDouble定義されています。NaN

public static final double NaN = 0.0d / 0.0;

あなたが説明する特別な動作は、JVMに組み込まれています。

于 2012-01-11T13:06:17.333 に答える
4

に従って、倍精度数の浮動小数点演算の IEEE 標準、

IEEE 倍精度浮動小数点標準表現には 64 ビット ワードが必要であり、左から右に 0 から 63 までの番号で表すことができます。

ここに画像の説明を入力 どこ、

S: Sign – 1 bit
E: Exponent – 11 bits
F: Fraction – 52 bits 

E=2047(すべてE1) であり、Fがゼロでない場合、( V=NaN"非数")

つまり、

すべてのEビットが 1 で、ゼロ以外のビットがあるF場合、数値はNaNです。

したがって、とりわけ、以下のすべての番号はNaN

0 11111111 0000000000000000010000000000000000000000000000000000 = NaN
1 11111111 0000010000000000010001000000000000001000000000000000 = NaN
1 11111111 0000010000011000010001000000000000001000000000000000 = NaN

特に、テストすることはできません

if (x == Double.NaN) 

Double.NaNすべての「非数」値は異なると見なされるため、特定の結果が に等しいかどうかを確認します。Double.isNaNただし、次の方法を使用できます。

if (Double.isNaN(x)) // check whether x is "not a number"
于 2015-01-30T15:56:31.317 に答える
3

NaN は「非数」を表す特別な値です。これは、 などの特定の無効な算術演算の結果でありsqrt(-1)、 という (場合によっては煩わしい) プロパティを持っていNaN != NaNます。

于 2012-01-11T13:04:10.017 に答える
2

Not a number は、結果が数値で表現できない操作の結果を表します。最も有名な演算は 0/0 で、その結果は不明です。

このため、NaN は何にも等しくありません (他の非数値を含む)。詳細については、ウィキペディアのページを確認してください: http://en.wikipedia.org/wiki/NaN

于 2012-01-11T13:07:15.687 に答える