J'ai un programme qui essaie de réduire une double
au nombre souhaité. Le résultat obtenu est NaN
.
Que signifie NaN
en Java?
Tiré de cette page :
"NaN" signifie "pas un nombre". "Nan" est produit si une opération à virgule flottante a certains paramètres d'entrée qui lui donnent un résultat non défini. Par exemple, 0.0 divisé par 0.0 est arithmétiquement non défini. Prendre la racine carrée d'un nombre négatif est également indéfini.
NaN
signifie "Pas un nombre" et est essentiellement une représentation d'une valeur en virgule flottante spéciale dans virgule flottante IEE 754). standard. NaN signifie généralement que la valeur est quelque chose qui ne peut pas être exprimé avec un nombre à virgule flottante valide.
Une conversion aboutira à cette valeur, lorsque la valeur en cours de conversion est différente, par exemple lors de la conversion d'une chaîne qui ne représente pas un nombre.
NaN
signifie "Pas un nombre" et est le résultat d'opérations non définies sur des nombres en virgule flottante, comme par exemple la division de zéro par zéro. (Notez que bien que diviser un nombre non nul par zéro soit aussi généralement non défini en mathématiques, cela ne donne pas NaN mais un infini positif ou négatif).
NaN
signifie "Pas un nombre." C'est une valeur spéciale en virgule flottante qui signifie que le résultat d'une opération n'a pas été défini ou ne peut pas être représenté sous forme de nombre réel.
Voir ici pour plus d'explications sur cette valeur.
NaN signifie pas un nombre. Il est utilisé pour signifier toute valeur mathématiquement non définie. Comme divisant 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
Postez votre programme ici si vous avez besoin de plus d'aide.
NaN = Pas un nombre.
Signifie pas un nombre. C'est une représentation courante d'une valeur numérique impossible dans de nombreux langages de programmation.
Ce n'est pas un gars Java, mais dans JS et d'autres langages, j'utilise plutôt "Pas un nombre", ce qui signifie qu'une opération l'a rendu non valide.
Cela signifie littéralement "Pas un nombre". Je soupçonne que quelque chose ne va pas avec votre processus de conversion.
Consultez la section Pas un nombre à cette référence
Pas une valeur en virgule flottante valide (par exemple, le résultat de la division par zéro)
Exemple minimal exécutable
La première chose que vous devez savoir, c'est que le concept de NaN est implémenté directement sur le matériel de la CPU.
Tous les principaux processeurs modernes semblent suivre IEEE 754 qui spécifie les formats à virgule flottante, et les NaN, qui ne sont que des valeurs flottantes spéciales, font partie de cette norme.
Par conséquent, le concept sera très similaire dans tous les langages, y compris Java qui émet simplement du code à virgule flottante directement vers la CPU.
Avant de continuer, vous voudrez peut-être tout d'abord lire les réponses suivantes que j'ai écrites:
Passons maintenant à l'action Java. La plupart des fonctions d'intérêt qui ne sont pas dans la langue principale résident à l'intérieur de 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));
}
}
_
Courir 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, à partir de cela, nous apprenons quelques choses:
d'étranges opérations flottantes qui n'ont aucun résultat raisonnable donnent à NaN:
0.0f / 0.0f
_sqrt(-1.0f)
log(-1.0f)
générer un NaN
.
En C, il est effectivement possible de demander que des signaux soient générés sur de telles opérations avec feenableexcept
pour les détecter, mais je ne pense pas que cela soit exposé en Java: Pourquoi la division entière par zéro 1 0 donne une erreur mais la virgule flottante 1/0.0 renvoie "Inf"?
opérations étranges qui sont à la limite de plus ou moins l'infini donnent cependant + - l'infini au lieu de NaN
1.0f / 0.0f
_log(0.0f)
_0.0
_ tombe presque dans cette catégorie, mais le problème est probablement que cela pourrait aller à plus ou moins l'infini, donc il a été laissé comme NaN.
si NaN est l'entrée d'une opération flottante, la sortie tend également à être NaN
il existe plusieurs valeurs possibles pour NaN _0x7fc00000
_, _0x7fc00001
_, _0x7fc00002
_, bien que x86_64 semble générer uniquement _0x7fc00000
_.
NaN et l'infini ont une représentation binaire similaire.
Décomposons quelques-uns d'entre eux:
_nan = 0x7fc00000 = 0 11111111 10000000000000000000000
positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000
negative_inf = 0xff800000 = 1 11111111 00000000000000000000000
| | |
| | mantissa
| exponent
|
sign
_
À partir de là, nous confirmons ce que IEEE754 spécifie:
Les NaN peuvent être positifs ou négatifs (bit du haut), bien que cela n'ait aucun effet sur les opérations normales
Testé sous Ubuntu 18.10 AMD64, OpenJDK 1.8.0_191.