100 votes

0,1 float est plus grand que 0,1 double. Je m'attendais à ce que ce soit faux

Laissez :

double d = 0.1;
float f = 0.1;

l'expression

(f > d)

retourner true ou false ?

Empiriquement, la réponse est true . Cependant, je m'attendais à ce que ce soit false .

Comme 0.1 ne peut pas être parfaitement représenté en binaire, alors que le double a 15 a 16 chiffres décimaux de précision, et le flottant a seulement 7 . Donc, ils sont tous deux inférieurs à 0.1 tandis que le double est plus proche de 0.1 .

J'ai besoin d'une explication exacte pour le true .

172voto

KennyTM Points 232647

Je dirais que la réponse dépend du mode d'arrondi lors de la conversion des double a float . float a 24 ans binaire bits de précision, et double a 53 ans. En binaire, 0,1 est :

0.1₁₀ = 0.0001100110011001100110011001100110011001100110011…₂
             ^        ^         ^   ^ 
             1       10        20  24

Donc si on arrondit en haut au 24ème chiffre, nous aurons

0.1₁₀ ~ 0.000110011001100110011001101

qui est supérieure à la valeur exacte et à l'approximation plus précise à 53 chiffres.

55voto

Sven Marnach Points 133943

Le nombre 0.1 sera arrondi à la représentation en virgule flottante la plus proche avec la précision donnée. Cette approximation peut être supérieure ou inférieure à 0,1, donc sans regarder les valeurs réelles, vous ne pouvez pas prédire si l'approximation en simple ou double précision est plus grande.

Voici à quoi la valeur en double précision est arrondie (en utilisant un interpréteur Python) :

>>> "%.55f" % 0.1
'0.1000000000000000055511151231257827021181583404541015625'

Et voici la valeur en simple précision :

>>> "%.55f" % numpy.float32("0.1")
'0.1000000014901161193847656250000000000000000000000000000'

Vous pouvez donc voir que l'approximation en simple précision est plus grande.

19voto

dutchrooster Points 191

Si vous convertissez .1 au binaire que vous obtenez :

0.000110011001100110011001100110011001100110011001100...

qui se répète pour toujours

En faisant correspondre les types de données, on obtient :

float(.1)  = %.00011001100110011001101
                                     ^--- note rounding
double(.1) = %.0001100110011001100110011001100110011001100110011010

Convertissez-le en base 10 :

float(.1)  = .10000002384185791015625
double(.1) = .100000000000000088817841970012523233890533447265625

Ceci est tiré d'un article écrit par Bruce Dawson. Vous pouvez le trouver ici :
Les doubles ne sont pas des flotteurs, ne les comparez pas.

5voto

Kip Points 37013

Je pense Commentaire d'Eric Lippert sur la question est en fait l'explication la plus claire, donc je la reposte comme une réponse :

Supposons que vous calculiez 1/9 en décimal à 3 chiffres et en décimal à 6 chiffres. 0,111 < 0,111111, n'est-ce pas ?

Supposons maintenant que vous calculez 6/9. 0.667 > 0.666667, c'est ça ?

On ne peut pas dire que 6/9 en décimale à trois chiffres soit 0,666 parce que ce n'est pas la décimale à trois chiffres la plus proche de 6/9 !

4voto

xan Points 3597

Puisqu'il ne peut pas être représenté exactement, comparer 1/10 en base 2 revient à comparer 1/7 en base 10.

1/7 = 0,142857142857... mais en comparant à différentes précisions en base 10 (3 contre 6 décimales), nous avons 0,143 > 0,142857.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X