Ho un programma che cerca di ridurre double
a un numero desiderato. L'output che ottengo è NaN
.
Cosa NaN
significa in Java?
Ho un programma che cerca di ridurre double
a un numero desiderato. L'output che ottengo è NaN
.
Cosa NaN
significa in Java?
Risposte:
Tratto da questa pagina :
"NaN" sta per "not a number". "Nan" viene prodotto se un'operazione in virgola mobile ha alcuni parametri di input che fanno sì che l'operazione produca un risultato indefinito. Ad esempio, 0,0 diviso per 0,0 è aritmeticamente indefinito. Anche il calcolo della radice quadrata di un numero negativo è indefinito.
NaN
ha l'interessante proprietà di essere l'unico "numero" che non è uguale a se stesso se confrontato. Quindi un comune (e in molte lingue l'unico) di prova se un numero x
è NaN
il seguente:boolean isNaN(x){return x != x;}
i
e alcuni linguaggi come Python lo affrontano molto bene ... Potrebbe non essere il caso di java
te
NaN
significa "Non un numero" ed è fondamentalmente una rappresentazione di un valore in virgola mobile speciale nello standard a virgola mobile IEE 754 . NaN generalmente significa che il valore è qualcosa che non può essere espresso con un numero in virgola mobile valido.
Una conversione risulterà in questo valore, quando il valore convertito è qualcos'altro, ad esempio quando si converte una stringa che non rappresenta un numero.
parseFloat()
o parseDouble
? O qualcos'altro?
NaN
significa "Non un numero" ed è il risultato di operazioni indefinite su numeri in virgola mobile, come ad esempio la divisione di zero per zero. (Notare che mentre la divisione di un numero diverso da zero per zero è solitamente indefinita anche in matematica, non si traduce in NaN ma in un infinito positivo o negativo).
NaN
significa "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.
Vedi qui per ulteriori spiegazioni di questo valore.
NaN sta per Not a Number. Viene utilizzato per indicare qualsiasi valore matematicamente indefinito. Come dividere 0,0 per 0,0. Puoi cercare qui per maggiori informazioni: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm
Pubblica il tuo programma qui se hai bisogno di ulteriore aiuto.
NaN = Not a Number.
Esempio minimo eseguibile
La prima cosa che devi sapere è che il concetto di NaN è implementato direttamente sull'hardware della CPU.
Tutte le principali CPU moderne sembrano seguire IEEE 754 che specifica i formati in virgola mobile e NaN, che sono solo valori speciali in virgola mobile, fanno parte di quello standard.
Pertanto, il concetto sarà molto simile in qualsiasi linguaggio, incluso Java che emette semplicemente codice in virgola mobile direttamente alla CPU.
Prima di procedere, potresti voler leggere prima le seguenti risposte che ho scritto:
Ora per alcune azioni Java. La maggior parte delle funzioni di interesse che non sono nella lingua principale risiedono all'interno 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));
}
}
Corri con:
javac Nan.java && java -ea Nan
Produzione:
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:
strane operazioni fluttuanti che non hanno alcun risultato sensato danno NaN:
0.0f / 0.0f
sqrt(-1.0f)
log(-1.0f)
generare un file NaN
.
In C, è effettivamente possibile richiedere che vengano generati segnali su tali operazioni feenableexcept
per rilevarli, ma non credo che sia esposto in Java: Perché la divisione intera per zero 1/0 dà errore ma virgola mobile 1 / 0.0 restituisce "Inf"?
operazioni strane che sono sul limite di più o meno infinito tuttavia danno + - infinito invece di NaN
1.0f / 0.0f
log(0.0f)
0.0
rientra quasi in questa categoria, ma probabilmente il problema è che potrebbe andare a più o meno infinito, quindi è stato lasciato come NaN.
se NaN è l'input di un'operazione floating, anche l'output tende ad essere NaN
ci sono vari valori possibili per NaN 0x7fc00000
, 0x7fc00001
, 0x7fc00002
, anche se x86_64 sembra generare solo 0x7fc00000
.
NaN e infinity hanno una rappresentazione binaria simile.
Analizziamo alcuni di loro:
nan = 0x7fc00000 = 0 11111111 10000000000000000000000
positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000
negative_inf = 0xff800000 = 1 11111111 00000000000000000000000
| | |
| | mantissa
| exponent
|
sign
Da questo confermiamo quanto specifica IEEE754:
I NaN possono essere positivi o negativi (bit superiore), sebbene ciò non abbia effetto sulle normali operazioni
Testato in Ubuntu 18.10 amd64, OpenJDK 1.8.0_191.
Non è un tipo Java, ma in JS e in altri linguaggi uso è "Not a Number", il che significa che alcune operazioni hanno fatto sì che diventasse un numero non valido.
Letteralmente significa "Non un numero". Sospetto che ci sia qualcosa di sbagliato nel tuo processo di conversione.
Controlla la sezione Non un numero a questo riferimento
Non è un valore in virgola mobile valido (ad esempio il risultato della divisione per zero)