En Java, qu'est-ce que NaN signifie?
Question
I a un programme qui cherche à se rétrécir vers le bas un double
à un nombre souhaité. La sortie que je reçois est NaN
.
Que signifie de NaN
en Java?
La solution
« NaN » signifie « pas un nombre ». "Nan" est produit si une virgule flottante opération a des paramètres d'entrée cette cause de l'opération de produit un résultat non défini. Par exemple, 0,0 divisé par 0,0 est arithmétiquement non défini. En prenant la racine carrée d'un nombre négatif est également défini.
Autres conseils
moyens de NaN
« Pas un numéro » et est essentiellement une représentation d'une valeur en virgule flottante spécial dans la section IEE 754 à virgule flottante la norme. NaN en général signifie que la valeur est quelque chose qui ne peut être exprimé avec un nombre à virgule flottante valide.
Une conversion se traduira par cette valeur, lorsque la valeur étant convertie est autre chose, par exemple lors de la conversion d'une chaîne qui ne représente pas un nombre.
moyens de NaN
« Pas un numéro » et est le résultat des opérations non définies sur les nombres à virgule flottante comme par exemple entre le zéro par zéro. (Notez que tout en divisant un nombre non nul par zéro est généralement défini non plus en mathématiques, il ne résulte pas de la NAN, mais dans l'infini positif ou négatif).
NaN signifie pas un numéro. Il est utilisé pour signifier une valeur mathématiquement non défini. Comme la division 0.0 par 0.0. Vous pouvez regarder ici pour plus d'informations: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm
Publier votre programme ici si vous avez besoin de plus d'aide.
NAN = Pas un numéro.
Moyens non un numéro. Il est une représentation commune pour une valeur numérique impossible dans de nombreux langages de programmation.
Pas un gars Java, mais dans d'autres langues JS et je l'utilise est « pas un numéro », ce qui signifie une opération a causé à devenir pas valide.
Cela signifie littéralement « Pas un numéro. » Je suspect quelque chose ne va pas avec votre processus de conversion.
Consultez la section Not A Number cette référence
Non une valeur à virgule flottante valide (par exemple le résultat de la division par zéro)
Exemple minimal runnable
La première chose que vous devez savoir, est que le concept de NaN est mis en œuvre directement sur le matériel du processeur.
Tous les grands processeurs modernes semblent suivre IEEE 754 qui spécifie flottante formats de points, et NaN , qui ne sont que des valeurs flottantes spéciales, font partie de cette norme.
Par conséquent, le concept sera le très similaire dans toutes les langues, y compris Java qui émet simplement un code à virgule flottante directement à la CPU.
Avant de poursuivre, vous voudrez peut-être d'abord lire les réponses suivantes que j'ai écrit:
- un recyclage rapide du format en virgule flottante IEEE 754: Qu'est-ce qu'un nombre à virgule flottante subnormale?
- un niveau inférieur de base NaN couverts en C / C ++: Quelle est la différence entre NaN silencieux et NaN de signalisation?
Maintenant, pour une action Java. La plupart des fonctions d'intérêt qui ne sont pas dans la langue de noyau à l'intérieur en direct 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));
}
}
Exécuter avec:
javac Nan.java && java -ea Nan
Sortie:
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
Donc, de ce que nous apprenons quelques petites choses:
-
bizarre opérations flottantes qui n'ont pas de résultat raisonnable donner NaN:
-
0.0f / 0.0f
-
sqrt(-1.0f)
-
log(-1.0f)
générer un
NaN
.En C, il est effectivement possible de signaux de demande à prélever sur ces opérations avec
feenableexcept
pour les détecter, mais je ne pense pas qu'il est exposé en Java: Pourquoi la division entière par zéro 1 / 0 erreur, mais donner à virgule flottante 1 / 0,0 renvoie "Inf"? -
-
opérations étranges qui sont sur la limite soit plus ou moins l'infini ne donnent toutefois + - infini au lieu de NaN
-
1.0f / 0.0f
-
log(0.0f)
0.0
tombe presque dans cette catégorie, mais probablement le problème est qu'il soit pourrait aller à plus ou moins l'infini, il a été laissé comme NaN. -
-
si NaN est l'entrée d'une opération flottante, la sortie tend également à être NaN
-
il y a plusieurs valeurs possibles pour NaN
0x7fc00000
,0x7fc00001
,0x7fc00002
, bien que x86_64 semble générer seulement0x7fc00000
. -
NaN et l'infini ont une représentation binaire similaire.
Soit la rupture de bas certains d'entre eux:
nan = 0x7fc00000 = 0 11111111 10000000000000000000000 positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000 negative_inf = 0xff800000 = 1 11111111 00000000000000000000000 | | | | | mantissa | exponent | sign
De ce que nous confirment ce IEEE754 précise:
- les deux NaN et infinités ont exposant == 255 (tous les)
- infinités == 0. mantisse Have Il n'y a donc que deux possibles infinités: + et -, différenciés par le bit de signe
- NaN a mantisse! = 0. Il y a donc plusieurs possibilités, à l'exception mantisse == 0 qui est infini
-
NaN peut être soit positive ou négative (en haut à bit), bien que cela n'a aucun effet sur le fonctionnement normal
Testé dans Ubuntu 18.10 amd64, OpenJDK 1.8.0_191.