Pourquoi la conversion de float en double change la valeur?
J'ai essayé de trouver la raison, mais je ne pouvais pas.
Quelqu'un peut-il m'aider?
Regardez l'exemple suivant.
float f;
f = 125.32f;
System.out.println("value of f = " + f);
double d = (double) 125.32f;
System.out.println("value of d = " + d);
C'est la sortie:
valeur de f = 125.32
valeur de d = 125.31999969482422
source d'informationauteur arthursfreire
Vous devez vous connecter pour publier un commentaire.
float
dans undouble
il n'y a pas de perte d'information. Chaquefloat
peut être représenté exactement comme undouble
.System.out.println
est la valeur exacte du nombre. Une exacte représentation décimale peut nécessiter jusqu'à environ 760 chiffres après la virgule. Au lieu de cela,System.out.println
imprime exactement le nombre de chiffres après la virgule qui permettent d'analyser la représentation décimale de retour dans l'originalfloat
oudouble
. Il y a plus dedouble
s, de sorte que lors de l'impression,System.out.println
besoin d'imprimer plus de chiffres avant la représentation devient sans ambiguïté.La valeur d'un
float
ne change pas lors de la conversion d'undouble
. Il y a une différence dans l'affichage des chiffres parce que plus de chiffres sont nécessaires pour distinguer undouble
de valeur de ses voisins, ce qui est requis par la documentation de Java. C'est la documentation detoString
qui est visée (par le biais de plusieurs liens) à partir de la documentation pourprintln
.La valeur exacte pour
125.32f
est 125.31999969482421875. Les deux voisins defloat
valeurs sont 125.3199920654296875 et 125.32000732421875. Observer que 125.32 est plus proche de 125.31999969482421875 que ce soit pour les voisins. Par conséquent, en affichant “125.32”, Java a pas fait preuve d'assez de chiffres, de sorte que la conversion en arrière à partir de la virgule chiffre d'float
reproduit la valeur de lafloat
passé àprintln
.Les deux voisins de
double
valeurs de 125.31999969482421875 sont 125.3199996948242045391452847979962825775146484375 et 125.3199996948242329608547152020037174224853515625. Observer que 125.32 est plus proche de ce dernier voisin qu'à la valeur d'origine. Par conséquent, l'impression de “125.32” ne contient pas assez de chiffres pour distinguer la valeur d'origine. Java doit imprimer plus de chiffres afin d'assurer une conversion de l'affiche chiffre de retour àdouble
reproduit la valeur de ladouble
passé àprintln
.La conversion de
float
àdouble
est un élargir la conversioncomme spécifié par le JLS. Un élargissement de conversion est défini comme un injective la cartographie d'un ensemble plus restreint dans sa surcouche. Par conséquent, le nombre représenté ne change pas après une conversion defloat
àdouble
.Plus d'informations concernant la mise à jour de votre question
Dans votre mise à jour de l'ajout d'un exemple qui est censé démontrer que le nombre a changé. Cependant, il ne montre que le représentation de chaîne le nombre a changé, en effet, c'est en raison de la précision additionnelle acquise grâce à la conversion de
double
. Notez que votre première sortie est juste un arrondissement de la deuxième sortie. Comme spécifié parDouble.toString
Depuis la côté des valeurs dans le type
double
sont beaucoup plus proches que dansfloat
plus de chiffres sont nécessaires pour se conformer à cette décision.Le 32 bits IEEE-754 nombre à virgule flottante la plus proche de 125.32 est en fait 125.31999969482421875. Assez proche, mais pas tout à fait là (c'est parce que les 0.32 est de répéter en binaire).
Lorsque vous lancez que de faire un double, c'est la valeur 125.31999969482421875 qui sera faite dans un double (125.32 est nulle part pour être trouvée à ce stade, les informations qu'il devrait vraiment finir dans .32 est complètement perdu) et de cours peut être représenté exactement par un double. Lorsque vous imprimez le double, l'impression de routine, il pense qu'il a plus de chiffres significatifs que il a vraiment (mais bien sûr, il ne pouvez pas le savoir), de sorte qu'il imprime à 125.31999969482422, qui est la plus petite virgule qui arrondit à l'exacte double (et de toutes les décimales de cette longueur, il est le plus proche).
La question de la précision des nombres à virgule flottante est vraiment indépendant de la langue, donc je vais être à l'aide de MATLAB dans mon explication.
La raison pour laquelle vous voyez une différence, c'est que certains numéros ne sont pas exactement représentable en nombre fixe de bits. Prendre
0.1
par exemple:Donc l'erreur dans l'approximation de
0.1
en simple précision devient plus grand quand vous le lancez en tant que double-nombre à virgule flottante. Le résultat est différent de son rapprochement si vous avez commencé directement en double précision.Comme déjà expliqué, tous les flotteurs peuvent être représentées exactement comme un double et la raison de votre problème, c'est que
System.out.println
effectue quelques erreurs lors de l'affichage de la valeur d'unfloat
oudouble
mais la méthode d'arrondissement n'est pas le même dans les deux cas.Pour voir la valeur exacte de la séance, vous pouvez utiliser un
BigDecimal
:sorties:
il ne fonctionne pas en java, car en java par défaut, il prendra de vraies valeurs comme double et, si nous déclarons une valeur float sans représentation du flotteur
comme
123.45 f
par défaut, il va le prendre comme un double et qu'il va provoquer une erreur que la perte de précision
La représentation de l'évolution des valeurs en raison de contrats de méthodes de convertir des valeurs numériques à un
String
en conséquencejava.lang.Float#toString(float)
etjava.lang.Double#toString(double)
tandis que la valeur reste la même. Il y a une partie commune dans la Javadoc des deux méthodes ci-dessus, qui développe des exigences pour les valeurs'String
représentation:Pour illustrer la similitude des parties significatives pour les valeurs de deux types, l'extrait de code suivant peut être exécuté:
Dans mon environnement, la sortie est:
De cette façon, vous pouvez voir que les valeurs de " signe, l'exposant sont les mêmes, alors que sa mantisse a été étendu conservé une partie importante (
11110101010001111010111
) exactement la même.L'utilisé l'extraction de la logique de la virgule flottante nombre de pièces: Un et Deux.
Les deux sont ce que Microsoft appelle "nombre approximatif de types de données."
Il y a une raison. Un flotteur a une précision de 7 chiffres, et un double 15. Mais je l'ai vu se produire de nombreuses fois que 8.0 - 1.0 - 6.999999999. C'est parce qu'ils ne sont pas garantis pour représenter un nombre décimal en fraction exactement.
Si vous avez besoin d'absolu, invariable précision, aller avec une virgule, ou de type intégral.