Почему Double.NaN == Double.NaN возвращает false? - PullRequest
151 голосов
/ 11 января 2012

Я просто изучал вопросы OCPJP и нашел этот странный код:

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

Когда я запустил код, я получил:

false
true

Как получается false, когда мы сравниваем две вещи, которые выглядят одинаково друг с другом? Что значит NaN?

Ответы [ 9 ]

136 голосов
/ 11 января 2012

NaN означает «Не число».

Спецификация языка Java (JLS), третье издание: :

Операция, которая переполняется, производит бесконечность со знаком, операция, которая переполняется, производит денормализованное значение или нулевой знак, а операция, которая не имеет математически определенного результата, производит NaN. Все числовые операции с NaN в качестве операнда производят NaN в результате. Как уже было описано, NaN неупорядочен, поэтому операция числового сравнения, включающая один или два NaN, возвращает false, а любое сравнение !=, включающее NaN, возвращает true, включая x!=x, когда x - это NaN. *

60 голосов
/ 11 января 2012

NaN по определению не равно ни одному числу, включая NaN.Это является частью стандарта IEEE 754 и реализуется процессором / FPU.Это не то, что JVM должна добавить для поддержки какой-либо логики.

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

Сравнение с NaN всегда возвращает неупорядоченный результат даже при сравнении с самим собой.... Предикаты равенства и неравенства не сигнализируют, поэтому x = x, возвращающий false, можно использовать для проверки, является ли x спокойным NaN.

Java рассматривает весь NaN как тихий NaN.

48 голосов
/ 11 января 2012

Почему эта логика

NaN означает Not a Number. Что не число? Что-нибудь. У вас может быть что угодно с одной стороны и что угодно с другой стороны, так что ничто не гарантирует, что оба равны. NaN рассчитывается с Double.longBitsToDouble(0x7ff8000000000000L) и, как вы можете видеть из документации longBitsToDouble:

Если аргумент является любым значением в диапазоне от 0x7ff0000000000001L до 0x7fffffffffffffffL или в диапазоне 0xfff0000000000001L через 0xffffffffffffffffL, результатом является NaN.

Кроме того, NaN логически обрабатывается внутри API.

<ч />

Документация

/** 
 * 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:

Если this и argument оба представляют Double.NaN, то equals метод возвращает true, хотя Double.NaN==Double.NaN имеет значение false.

Double.NaN.equals(Double.NaN);
14 голосов
/ 01 октября 2015

Это может быть не прямой ответ на вопрос. Но если вы хотите проверить, что-то равно Double.NaN, вы должны использовать это:

double d = Double.NaN
Double.isNaN(d);

Это вернет true

6 голосов
/ 11 января 2012

Javadoc для Double.NaN говорит сам за себя:

Константа, содержащая значение Not-a-Number (NaN) типа double.Это эквивалентно значению, возвращаемому Double.longBitsToDouble(0x7ff8000000000000L).

Интересно, что источник для Double определяет NaN, таким образом:

public static final double NaN = 0.0d / 0.0;

Особое поведение, которое вы описываете:встроенный в JVM.

3 голосов
/ 30 января 2015

согласно, Стандарт IEEE для арифметики с плавающей запятой для чисел двойной точности,

Стандартное представление двойной точности с плавающей запятой IEEE требует 64-битного слова, которое может бытьобозначены номерами от 0 до 63, слева направо

enter image description here, где

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

Если E=2047 (все E равны 1) и 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"
3 голосов
/ 11 января 2012

NaN - это специальное значение, которое обозначает «не число»;это результат некоторых недопустимых арифметических операций, таких как sqrt(-1), и имеет (иногда раздражающее) свойство, которое NaN != NaN.

2 голосов
/ 11 января 2012

Не число представляет результат операций, результат которых не может быть представлен числом. Самая известная операция - 0/0, результат которой неизвестен.

По этой причине NaN не равен чему-либо (включая другие значения не числа). Для получения дополнительной информации, просто проверьте страницу википедии: http://en.wikipedia.org/wiki/NaN

0 голосов
/ 26 февраля 2018

Согласно этой ссылке , он имеет различные ситуации и трудно запомнить.Вот как я их помню и различаю.NaN означает «математически не определено», например: «результат 0, деленный на 0, не определен», и поскольку он не определен, то «сравнение, связанное с неопределенным, конечно, не определено».Кроме того, это больше похоже на математические предпосылки.С другой стороны, как положительная, так и отрицательная бесконечность предопределены и окончательны, например, «положительное или отрицательное бесконечно большое хорошо определено математически».

...