2010-01-28 13 views
8

Il documentation for java.lang.Double.NaN dice che èQuali sono gli altri valori NaN?

Un possesso di un valore costante Not-a-Number (NaN) di tipo double. È equivalente al valore restituito da Double.longBitsToDouble(0x7ff8000000000000L).

Questo sembra implicare che ce ne sono altri. In tal caso, come posso ottenerli e può essere fatto portabilmente?

Per essere chiari, mi piacerebbe trovare i valori doublex tale che

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

e

Double.isNaN(x) 

sono entrambe vere.

+0

Vuoi dire che ci sono altre 'java.lang * NaN'..? –

+0

@Dominic: No - Ho aggiunto quello che penso sia un chiarimento alla domanda. –

risposta

8

È necessario doubleToRawLongBits anziché doubleToLongBits.

doubleToRawLongBits estrae la rappresentazione binaria effettiva. doubleToLongBits no, converte tutti i valori NaN in default con lo 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)); 

uscita:

7FF8000000000000 
7FF8000000000000 
7FF8000000000000 
7FF8000000000100 
+0

Grazie per il suggerimento su 'doubleToRawLongBits'! –

2

IEEE 754 definisce un NaN come un numero con tutti i bit di esponente che sono 1 e un numero diverso da zero nella mantissa.

Così per un numero di singola precisione siete alla ricerca di: gestisce

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

Java questo modo:

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 

In sintesi, è possibile utilizzare qualsiasi NaN che si desidera, che è conforme alla regole sopracitate (tutti i bit 1 in esponente e mantissa! = 0).

+0

L'ultima affermazione non ha senso. 'Double.doubleToLongBits (...)' è un 'long', che è implicitamente convertito in' double', autoboxed e confrontato con * reference * con 'n2'. – finnw

+0

Probabilmente nell'ultima riga dovrebbe essere 'Double.doubleToLongBits (n2)! = Double.doubleToLongBits (Double.NaN)'? –

+0

Questo stampa 'false', perché' doubleToLongBits' converte tutti i 'NaN' sullo stesso valore. Ma è vero se usi 'doubleToRawLongBits'. – finnw

5

Java utilizza IEEE 754 per i suoi numeri in virgola mobile e quindi segue le loro regole.

Secondo la Wikipedia page on NaN esso è definito così:

Un esempio bit-wise di virgola mobile IEEE standard di precisione singola NaN: x111 1111 1axx xxxx xxxx xxxx xxxx xxxx dove x significa non importa.

Quindi ci sono alcuni modelli di bit che sono tutti valori NaN.

+0

Grazie. Questo è garantito per essere portabile su macchine virtuali? –

+1

@simonn: quella domanda mi farebbe fermare per un momento: in che modo esattamente vuoi usare questo fatto? Cerchi di inviare informazioni in-band all'interno del valore NaN di un 'double'? –

+0

Sort of. Sto cercando di emulare la semantica di un sistema in cui ci sono diversi valori che agiscono tutti come NaN, ma sono distinguibili. –