27 votes

Pourquoi la boucle utilisant un double échoue-t-elle

Je regarde d'anciennes questions d'examen (actuellement la première année d'université) et je me demande si quelqu'un pourrait expliquer un peu plus en détail pourquoi la boucle for ne se termine pas quand elle est censée le faire. Pourquoi cela arrive-t-il? Je comprends qu'il saute 100,0 à cause d'une erreur d'arrondi ou quelque chose, mais pourquoi?

 for(double i = 0.0; i != 100; i = i +0.1){
    System.out.println(i);
}
 

42voto

Richard Tingle Points 8054

Le nombre de 0,1 ne peut pas être exactement représenté en binaire, comme dans beaucoup de 1/3 ne peut pas être représentée exactement en décimal, en tant que tel vous ne pouvez pas garantir que:

0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1==1

C'est parce qu'en binaire:

0.1=(binary)0.00011001100110011001100110011001....... forever

Cependant un double ne peut pas contenir une précision infinie et donc, tout comme nous approximative 1/3 de 0.3333333 doit donc la représentation binaire approximatif de 0,1.


Élargi décimal analogie

En décimal, vous pouvez constater que

1/3+1/3+1/3
=0.333+0.333+0.333
=0.999

C'est exactement le même problème. Il ne devrait pas être perçu comme une faiblesse de nombres en virgule flottante comme notre propre système décimal a les mêmes difficultés (mais pour des numéros différents, quelqu'un avec une base-3 système serait-il trouver étrange que nous avons lutté pour représenter 1/3). C'est pourtant une question d'être conscient de.

Démo

Une démonstration en direct fournis par Andrea Ligios montre ces erreurs de construction.

11voto

hevi Points 523

Ordinateurs (au moins celles actuelles), travaille avec des données binaires. En outre, il y a une limitation de longueur pour les ordinateurs de processus dans leurs unités arithmétiques et logiques (c'est à dire 32bits, 64bits, etc). Représentant des entiers de la forme binaire est simple, au contraire, nous ne pouvons pas dire la même chose pour floating points. 64 bits floating point representation

Comme indiqué ci-dessus, il existe un moyen de représenter les floating points selon la norme IEEE-754, qui est également acceptée comme étant de facto par le processeur producteurs et les logiciels les gars c'est pourquoi il est important pour chacun de savoir à ce sujet.

Si l'on regarde la valeur maximale d'un double en java (le Double.MAX_VALUE) est de 1.7976931348623157E308 (>10^307). seulement avec la version 64 bits, un très grand nombre peut être représenté toutefois problème, c'est la précision.

Comme '==' et '!=' les opérateurs de comparer les numéros de bit-à-bit, dans votre cas 0.1+0.1+0.1 n'est pas égal à 0,3 en termes de bits, ils sont représentés.

En conclusion, pour s'adapter énorme des nombres à virgule flottante dans quelques bits d'habiles ingénieurs a décidé de sacrifier la précision. Si vous travaillez sur les points que vous ne devriez pas utiliser '==' ou '!=' sauf si vous êtes sûr de ce que vous faites.

10voto

Marko Topolnik Points 77257

En règle générale, n'utilisez jamais double pour effectuer une itération en raison d'erreurs d'arrondi (0,1 peut sembler agréable lorsqu'il est écrit en base 10, mais essayez de l'écrire en base 2 - ce qui est double les usages). Ce que vous devez faire est d'utiliser une variable int simple pour itérer et calculer le double partir d'elle.

 for (int i = 0; i < 1000; i++)
  System.out.println(i/10.0);
 

8voto

hexafraction Points 16201

Tout d'abord, je vais vous expliquer certaines choses à propos de double. Ce sera effectivement lieu en base dix pour faciliter la compréhension.

Prendre la valeur d'un tiers, et essayer de l'exprimer en base dix. Vous obtenez 0.3333333333333.... Disons que nous avons besoin d'arrondir à 4 places. Nous obtenons 0.3333. Maintenant, nous allons ajouter un autre 1/3. Nous obtenons 0.6666333333333.... qui des tours à 0.6666. Nous allons ajouter un autre 1/3. Nous obtenons 0.9999, pas 1.

La même chose arrive avec deux de base et un dixième. Vous allez depuis de 0,110 0,110 est la répétition d'une valeur binaire(comme 0.1666666... en base dix), vous aurez juste assez d'erreur de manquer une centaine de quand vous y arrivez.

1/2 peut être représenté dans la base de dix très bien, et 1/5 pouvez ainsi. C'est parce que le premier des facteurs du dénominateur sont un sous-ensemble des facteurs de la base. Ce n'est pas le cas pour un tiers dans la base de dix ou un dixième dans la base de deux.

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