Каковы другие значения NaN? - PullRequest
8 голосов
/ 28 января 2010

Документация для java.lang.Double.NaN говорит, что это

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

Кажется, это подразумевает, что есть и другие. Если да, то как мне их достать, и можно ли это сделать переносимо?

Для ясности, я хотел бы найти double значения x, такие что

Double.doubleToRawLongBits(x) != Double.doubleToRawLongBits(Double.NaN)

и

Double.isNaN(x)

оба истинны.

Ответы [ 3 ]

8 голосов
/ 28 января 2010

Вам нужно doubleToRawLongBits вместо doubleToLongBits.

doubleToRawLongBits извлекает фактическое двоичное представление. doubleToLongBits нет, сначала он конвертирует все NaN в значение по умолчанию NaN.

double n = Double.longBitsToDouble(0x7ff8000000000000L); // default NaN
double n2 = Double.longBitsToDouble(0x7ff8000000000100L); // also a NaN, but M != 0

System.out.printf("%X\n", Double.doubleToLongBits(n));
System.out.printf("%X\n", Double.doubleToRawLongBits(n));
System.out.printf("%X\n", Double.doubleToLongBits(n2));
System.out.printf("%X\n", Double.doubleToRawLongBits(n2));

выход:

7FF8000000000000
7FF8000000000000
7FF8000000000000
7FF8000000000100
6 голосов
/ 28 января 2010

Java использует IEEE 754 для своих чисел с плавающей запятой и поэтому следует их правилам.

Согласно странице Википедии о NaN она определяется следующим образом:

Битовый пример стандартного числа IEEE с плавающей запятой NaN: x111 1111 1axx xxxx xxxx xxxx xxxx xxxx, где x означает пофиг

Таким образом, существует довольно много битовых комбинаций, каждая из которых является NaN значениями.

2 голосов
/ 28 января 2010

IEEE 754 определяет NaN как число со всеми показательными битами, которые равны 1, и ненулевое число в мантиссе.

Так что для числа с одинарной точностью вы ищете:

S     E            M
x  11111111   xxxxxx....xxx (with M != 0)

Java обрабатывает это так:

Double n = Double.longBitsToDouble(0x7ff8000000000000L); // default NaN
Double n2 = Double.longBitsToDouble(0x7ff8000000000100L); // also a NaN, but M != 0

System.out.println(n.isNaN()); // true
System.out.println(n2.isNaN()); // true
System.out.println(n2 != Double.doubleToLongBits(Double.NaN)); // true

Для суммирования вы можете использовать любой NaN, который вы хотите, который соответствует вышеупомянутым правилам (все биты 1 в экспоненте и мантиссе! = 0).

...