Domanda
Ho un programma che tenta di compattare un basso double
ad un numero desiderato. L'output che ottengo è NaN
.
Che cosa significa NaN
media in Java?
Soluzione
"nan" sta per "non un numero". "Nan" viene prodotta se un punto floating operazione ha alcuni parametri di input che causa l'operazione di prodotti qualche risultato indefinito. Per esempio, 0.0 diviso per 0.0 è aritmeticamente indefinito. Prendendo la radice quadrata di un numero negativo è anche indefinito.
Altri suggerimenti
mezzi NaN
“Not a Number” ed è fondamentalmente una rappresentazione di un particolare valore in virgola mobile nel IEE 754 floating point norma . NaN generalmente significa che il valore è qualcosa che non può essere espresso con un numero a virgola mobile valido.
Una conversione si tradurrà in questo valore, quando l'essere valore convertito è qualcosa di diverso, ad esempio quando si converte una stringa che non rappresenta un numero.
mezzi NaN
"non un numero" ed è il risultato di operazioni non definiti su numeri in virgola mobile come ad esempio divisione per zero a zero. (Si noti che mentre la divisione di un numero diverso da zero per zero è anche di solito non definito in matematica, non comporti NaN ma infinito positivo o negativo).
mezzi NaN
"Non è un numero." È un valore in virgola mobile speciale che significa che il risultato di un'operazione non è stato definito o non rappresentabile come numero reale.
qui maggiori spiegazioni di questo valore.
NaN sta per Not a Number. E 'utilizzato per indicare qualsiasi valore che è matematicamente indefinito. Come dividendo 0,0 da 0,0. Si può guardare qui per maggiori informazioni: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm
Inserisci il tuo programma di qui se avete bisogno di più aiuto.
NaN = non un numero.
Mezzi Not a Number. Si tratta di una rappresentazione comune per un valore numerico impossibile in molti linguaggi di programmazione.
Non è un ragazzo di Java, ma in JS e altre lingue lo uso di "Not a Number", che significa qualche operazione la conseguenza di rendere non un numero valido.
E 'letteralmente significa "Not a Number". Ho il sospetto che qualcosa non va con il vostro processo di conversione.
Controlla la sezione non un numero a questo riferimento
Non un valore a virgola mobile valido (per esempio il risultato della divisione per zero)
Minimal esempio eseguibile
La prima cosa che dovete sapere, è che il concetto di NaN è implementato direttamente sull'hardware della CPU.
Tutte le principali CPU moderne sembrano seguire IEEE 754 che specifica floating point formati, e NaN , che sono i valori appena apposita spatola, fanno parte della norma.
Pertanto, il concetto sarà molto simile attraverso qualsiasi lingua, compreso Java che emette solo codice virgola mobile direttamente alla CPU.
Prima di procedere, si potrebbe desiderare di leggere prima le seguenti risposte che ho scritto:
- un rapido aggiornamento del formato punto IEEE 754 flottante: Che cosa è un numero in virgola di sotto della norma floating?
- alcune nozioni di base di livello inferiore NaN coperti tramite C / C ++: Qual è la differenza tra tranquilla Nan e NaN di segnalazione?
Ora per una certa azione di Java. La maggior parte delle funzioni di interesse che non sono nella lingua nucleo all'interno vivo java.lang.Float
.
Nan.java
import java.lang.Float;
import java.lang.Math;
public class Nan {
public static void main(String[] args) {
// Generate some NaNs.
float nan = Float.NaN;
float zero_div_zero = 0.0f / 0.0f;
float sqrt_negative = (float)Math.sqrt(-1.0);
float log_negative = (float)Math.log(-1.0);
float inf_minus_inf = Float.POSITIVE_INFINITY - Float.POSITIVE_INFINITY;
float inf_times_zero = Float.POSITIVE_INFINITY * 0.0f;
float quiet_nan1 = Float.intBitsToFloat(0x7fc00001);
float quiet_nan2 = Float.intBitsToFloat(0x7fc00002);
float signaling_nan1 = Float.intBitsToFloat(0x7fa00001);
float signaling_nan2 = Float.intBitsToFloat(0x7fa00002);
float nan_minus = -nan;
// Generate some infinities.
float positive_inf = Float.POSITIVE_INFINITY;
float negative_inf = Float.NEGATIVE_INFINITY;
float one_div_zero = 1.0f / 0.0f;
float log_zero = (float)Math.log(0.0);
// Double check that they are actually NaNs.
assert Float.isNaN(nan);
assert Float.isNaN(zero_div_zero);
assert Float.isNaN(sqrt_negative);
assert Float.isNaN(inf_minus_inf);
assert Float.isNaN(inf_times_zero);
assert Float.isNaN(quiet_nan1);
assert Float.isNaN(quiet_nan2);
assert Float.isNaN(signaling_nan1);
assert Float.isNaN(signaling_nan2);
assert Float.isNaN(nan_minus);
assert Float.isNaN(log_negative);
// Double check that they are infinities.
assert Float.isInfinite(positive_inf);
assert Float.isInfinite(negative_inf);
assert !Float.isNaN(positive_inf);
assert !Float.isNaN(negative_inf);
assert one_div_zero == positive_inf;
assert log_zero == negative_inf;
// Double check infinities.
// See what they look like.
System.out.printf("nan 0x%08x %f\n", Float.floatToRawIntBits(nan ), nan );
System.out.printf("zero_div_zero 0x%08x %f\n", Float.floatToRawIntBits(zero_div_zero ), zero_div_zero );
System.out.printf("sqrt_negative 0x%08x %f\n", Float.floatToRawIntBits(sqrt_negative ), sqrt_negative );
System.out.printf("log_negative 0x%08x %f\n", Float.floatToRawIntBits(log_negative ), log_negative );
System.out.printf("inf_minus_inf 0x%08x %f\n", Float.floatToRawIntBits(inf_minus_inf ), inf_minus_inf );
System.out.printf("inf_times_zero 0x%08x %f\n", Float.floatToRawIntBits(inf_times_zero), inf_times_zero);
System.out.printf("quiet_nan1 0x%08x %f\n", Float.floatToRawIntBits(quiet_nan1 ), quiet_nan1 );
System.out.printf("quiet_nan2 0x%08x %f\n", Float.floatToRawIntBits(quiet_nan2 ), quiet_nan2 );
System.out.printf("signaling_nan1 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan1), signaling_nan1);
System.out.printf("signaling_nan2 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan2), signaling_nan2);
System.out.printf("nan_minus 0x%08x %f\n", Float.floatToRawIntBits(nan_minus ), nan_minus );
System.out.printf("positive_inf 0x%08x %f\n", Float.floatToRawIntBits(positive_inf ), positive_inf );
System.out.printf("negative_inf 0x%08x %f\n", Float.floatToRawIntBits(negative_inf ), negative_inf );
System.out.printf("one_div_zero 0x%08x %f\n", Float.floatToRawIntBits(one_div_zero ), one_div_zero );
System.out.printf("log_zero 0x%08x %f\n", Float.floatToRawIntBits(log_zero ), log_zero );
// NaN comparisons always fail.
// Therefore, all tests that we will do afterwards will be just isNaN.
assert !(1.0f < nan);
assert !(1.0f == nan);
assert !(1.0f > nan);
assert !(nan == nan);
// NaN propagate through most operations.
assert Float.isNaN(nan + 1.0f);
assert Float.isNaN(1.0f + nan);
assert Float.isNaN(nan + nan);
assert Float.isNaN(nan / 1.0f);
assert Float.isNaN(1.0f / nan);
assert Float.isNaN((float)Math.sqrt((double)nan));
}
}
Esegui con:
javac Nan.java && java -ea Nan
Output:
nan 0x7fc00000 NaN
zero_div_zero 0x7fc00000 NaN
sqrt_negative 0xffc00000 NaN
log_negative 0xffc00000 NaN
inf_minus_inf 0x7fc00000 NaN
inf_times_zero 0x7fc00000 NaN
quiet_nan1 0x7fc00001 NaN
quiet_nan2 0x7fc00002 NaN
signaling_nan1 0x7fa00001 NaN
signaling_nan2 0x7fa00002 NaN
nan_minus 0xffc00000 NaN
positive_inf 0x7f800000 Infinity
negative_inf 0xff800000 -Infinity
one_div_zero 0x7f800000 Infinity
log_zero 0xff800000 -Infinity
Quindi da questo impariamo alcune cose:
-
strano operazioni che non hanno alcun sensibile risultato dare NaN galleggiante:
-
0.0f / 0.0f
-
sqrt(-1.0f)
-
log(-1.0f)
generare un
NaN
.In C, in realtà è possibile segnali di richiesta per essere sollevata su tali operazioni con
feenableexcept
per rilevarli, ma non credo che sia esposto in Java: Perché la divisione intera per zero 1 / 0 errore dare, ma in virgola mobile 1 / 0.0 restituisce "Inf"? -
-
Operazioni strani che si trovano sul limite di una più o meno infinito comunque danno + - infinito invece di NaN
-
1.0f / 0.0f
-
log(0.0f)
0.0
quasi rientra in questa categoria, ma probabilmente il problema è che potrebbe o andare a più o meno infinito, così è stato lasciato come NaN. -
-
se NaN è l'ingresso di un'operazione galleggiante, l'uscita tende anche ad essere NaN
-
ci sono più valori possibili per NaN
0x7fc00000
,0x7fc00001
,0x7fc00002
, anche se x86_64 sembra generare solo0x7fc00000
. -
Nan e l'infinito sono rappresentazione binaria simile.
pausa di deluso alcuni di loro:
nan = 0x7fc00000 = 0 11111111 10000000000000000000000 positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000 negative_inf = 0xff800000 = 1 11111111 00000000000000000000000 | | | | | mantissa | exponent | sign
Da ciò si conferma ciò che IEEE754 precisa:
- sia NaN e infiniti hanno esponente == 255 (tutti quelli)
- infiniti Hanno mantissa == 0. Non ci sono quindi solo due possibili infiniti: + e -, differenziati per il bit di segno
- Nan ha mantissa! = 0. Ci sono quindi diverse possibilità, ad eccezione di mantissa == 0 che è l'infinito
-
NaNs può essere positivo o negativo (alto bit), anche se questo non ha alcun effetto sulle normali attività
Testato in Ubuntu 18.10 amd64, OpenJDK 1.8.0_191.