web-dev-qa-db-fra.com

Est-ce que le doublage en flottant renvoie toujours la même valeur?

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.

21
user925777

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.

12
phoog

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.

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:

  • David Goldberg. 1991. Ce que tout informaticien devrait savoir sur l'arithmétique en virgule flottante . ACM Comput. Surv. 23, 1 (mars 1991), 5-48. DOI = 10.1145/103162.103163 http://doi.acm.org/10.1145/103162.103163

    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.

6
Nicholas Carey

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.

1
supercat

É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

1
Tigran

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.

0
Ethan Brown

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.

0
Kendall Frey