Le passage de double
à float
produit-il toujours le même résultat, ou peut-il y avoir des "différences d'arrondi"?
Par exemple, x
est-il dans
float x = (float)0.123456789d;
toujours la même valeur?
Qu'en est-il lorsque vous lancez float à doubler, puis que vous le remettez à flot c'est-à-dire. (float)(double)someFloat
?
Principalement intéressé par les résultats en C #, mais n'hésitez pas à le partager si vous avez des connaissances sur la façon dont cela fonctionne dans d'autres langues.
Les résultats ne doivent pas dépendre de la langue, sauf si la langue diffère de la spécification IEEE.
Tous les flottants peuvent être représentés exactement comme des doublons, de sorte que le va-et-vient aller-retour-double-flottant doit donner la même valeur que celle avec laquelle vous avez commencé.
De même, attribuer à float toute valeur double doit toujours donner le même résultat, mais il existe bien entendu de nombreuses valeurs doubles différentes qui tronqueraient à la même valeur float.
Si vous downcast} _ une double
à une float
, vous perdez en précision et en données. La conversion d'une float
en une double
est une conversion élargissement; aucune donnée n'est perdue si elle est ensuite arrondie ... c'est-à-dire, sauf si vous faites quelque chose à la valeur avant de la convertir en float.
Les nombres en virgule flottante sacrifient la précision et l'exactitude pour plage. Les flotteurs à simple précision offrent une précision de 32 bits. la double précision vous donne 64 bits. Mais ils peuvent représenter des valeurs bien en dehors des limites que la précision sous-jacente indiquerait.
C # float
et double
sont des valeurs à virgule flottante IEEE 754.
float
est une valeur IEEE 754 simple précision (32 bits) et consiste en un
double
est valeur IEEE 754 en double précision (64 bits) et consiste en un
La précision effective de la mantisse est supérieure de 1 bit à sa taille apparente (magick à virgule flottante).
Quelques ressources en virgule flottante CLR pour vous:
Ce document est probablement le document canonique sur les périls et les pièges de l'arithmétique en virgule flottante. Si vous n'êtes pas membre de l'ACM, cliquez sur le lien sur le titre pour trouver les téléchargements publics de l'article:
Abstrait
L'arithmétique en virgule flottante est considérée par beaucoup comme un sujet ésotérique . Ceci est plutôt surprenant, car la virgule flottante est omniprésente dans les systèmes informatiques: Presque toutes les langues ont un type de données à virgule flottante; ordinateurs des PC à les supercalculateurs ont des accélérateurs à virgule flottante; la plupart des compilateurs seront appelés compiler des algorithmes à virgule flottante de temps en temps; et pratiquement tous les opérateurs Le système doit répondre aux exceptions en virgule flottante telles que le dépassement de capacité. Ce papier présente un tutoriel sur les aspects de la virgule flottante qui ont un impact direct sur concepteurs de systèmes informatiques. Cela commence par un fond sur virgule flottante erreur de représentation et d’arrondi, continue avec une discussion sur le flottant IEEE point standard, et se termine avec des exemples de la façon dont les constructeurs de systèmes informatiques peuvent meilleur support virgule flottante.
Dans certains cas, la représentation float
la plus proche d'une quantité numérique peut différer de la valeur obtenue en arrondissant la représentation double
la plus proche à une float
. 12344.321.4999999991 et 12.345.678.50000000093 sont deux de ces quantités. Les nombres entiers au-dessus et au-dessous de ces deux quantités sont précisément représentables sous la forme float
, mais la double
la plus proche de chacune d'elles a une partie fractionnaire de exactement 0,5. La conversion de telles valeurs double
(entre 2 ^ 23 et 2 ^ 24, avec une fraction de exactement 0,5) en float
sera arrondie au nombre entier pair le plus proche; le compilateur finira par arrondir à la valeur qui aurait été plus proche du nombre initial.
Notez qu'en pratique, le compilateur semble analyser les nombres avec double
, puis les convertir en float
. Ainsi, même si 12344321.4999999991f doit être arrondi à 12344321f, il arrondit à la place à 12344322f. De même, 12345678.50000000093f doit arrondir à 12345679f mais à 12345678f. Ainsi, même dans les cas où la conversion en double
et ensuite float
perd en précision, une telle perte de conversion ne peut pas être évitée en spécifiant directement des nombres avec float
.
Incidemment, les valeurs 12344321.4999999992f et 12345678.50000000094f sont correctement arrondies.
Étant donné qu'ils ont une précision différente, même si vous passez d'une précision moindre à une précision plus large (je suppose que c'est en fait votre doute), le résultat ne peut pas être toujours identique.
Les opérations en virgule flottante, en particulier la fonte, font toujours l’objet de tronquer/arrondir et de tout autre type de approximation .
Les nombres en virgule flottante en C # sont stockés au format IEEE 754 (http://en.wikipedia.org/wiki/IEEE_754). Ce format comporte deux parties: les chiffres et l'exposant. Les doubles contiennent 52 chiffres et les flotteurs 23 chiffres. La base est 2, pas dix. Ainsi, pour votre exemple ci-dessus (0.123456789), les chiffres seraient 111010110111100110100010101 (la représentation binaire de 123456789). C'est 27 chiffres, ce qui convient parfaitement dans un double, mais pas dans un flottant, alors oui, la précision serait perdue lors de la conversion aller-retour.
D'autre part, si votre numéro était 0,123456, les chiffres seraient 11110001001000000 (17 chiffres), ce qui correspond aisément à un nombre à virgule flottante ou décimale. Vous ne perdriez donc aucune précision dans un transfert aller-retour.
Un double devrait pouvoir contenir exactement toutes les valeurs possibles d'un float. Transformer un float en double ne doit pas changer la valeur, et revenir en arrière devrait renvoyer la valeur d'origine, tant que vous n'avez pas effectué de calcul sur le double entre-temps.