Почему удваивается.NaN = = Двойной.NaN return false?


Я просто изучал вопросы 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 144

9 ответов:

NaN означает "не число".

спецификация языка Java (JLS) третье издание говорит:

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

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

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

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

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

зачем такая логика

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

если аргумент имеет любое значение в диапазоне 0x7ff0000000000001L через 0x7fffffffffffffffL или 0xfff0000000000001L через 0xffffffffffffffffL, результат a 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);

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

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

вернет true

The javadoc для двойной.Нэн говорит:

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

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

public static final double NaN = 0.0d / 0.0;

специальное поведение, которое вы описываете, жестко связано с JVM.

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

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

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

enter image description here где,

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

если E=2047 (всего E are 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"

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

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

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