2010-01-28 3 views
8

documentation for java.lang.Double.NaN говорит, что этоКаковы другие значения NaN?

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

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

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

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

и

Double.isNaN(x) 

оба являются истинными.

+0

Вы имеете в виду есть другие 'java.lang * NaN'..? –

+0

@ Dominic: Нет. Я добавил то, что, по моему мнению, является разъяснением вопроса. –

ответ

8

doubleToRawLongBits, а не doubleToLongBits.

doubleToRawLongBits извлекает фактическое двоичное представление. doubleToLongBits нет, он преобразует все NaN s по умолчанию 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 
+0

Спасибо за отзыв о 'doubleToRawLongBits'! –

2

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).

+0

Последнее утверждение не имеет смысла. 'Double.doubleToLongBits (...)' является 'long', который неявно преобразуется в' double', автобокс и сравнивается * reference * с 'n2'. – finnw

+0

Возможно, в последней строке должно быть 'Double.doubleToLongBits (n2)! = Double.doubleToLongBits (Double.NaN)'? –

+0

Это печатает 'false', потому что' doubleToLongBits' преобразует все 'NaN' в одно и то же значение. Но это правда, если вы используете 'doubleToRawLongBits'. – finnw

5

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

В соответствии с Wikipedia page on NaN она определяется следующим образом:

Побитового пример IEEE с плавающей точкой стандартной одинарной точностью NaN: x111 1111 1axx xxxx xxxx xxxx xxxx xxxx, где x означает все равно.

Таким образом, существует немало битовых шаблонов, все из которых являются значениями NaN.

+0

Спасибо. Гарантировано ли это переносимость через виртуальные машины? –

+1

@simonn: этот вопрос заставит меня остановиться на мгновение: как именно вы хотите использовать этот факт? Вы пытаетесь представить внутриполосную информацию внутри значения NaN 'double'? –

+0

Вид. Я пытаюсь подражать семантике системы, где есть несколько разных значений, которые все действуют как NaN, но они различимы. –