54 votes

La double multiplication est-elle rompue dans .NET?

Si j'exécute l'expression suivante en C #:

 double i = 10*0.69;
 

i est: 6.8999999999999995 . Pourquoi?

Je comprends que des nombres tels que 1/3 peuvent être difficiles à représenter en binaire car ils ont des décimales infinies mais ce n’est pas le cas pour 0.69. Et 0,69 peut facilement être représenté en binaire, un nombre binaire pour 69 et un autre pour indiquer la position de la décimale.

Comment est-ce que je travaille autour de ceci? Utilisez le type decimal ?

156voto

Jon Skeet Points 692016

Parce que vous avez mal compris arithmétique à virgule flottante et la façon dont les données sont stockées.

En fait, votre code n'est pas effectivement un de l'arithmétique au moment de l'exécution, dans ce cas particulier - le compilateur aura fait, puis enregistré une constante dans l'exécutable généré. Toutefois, il ne peut pas stocker une valeur exacte de 6,9, parce que cette valeur ne peut pas être précisément représentés en virgule flottante format de point, tout comme 1/3 ne peut pas être précisément stockées dans une décimale de la représentation.

Voir si cet article vous aide.

53voto

Russell Steen Points 4081

pourquoi ne pas le cadre de travail autour de cela et cacher ce problème, de moi et de me donner la droit de réponse,de 0,69!!!

Arrêter de se comporter comme un gestionnaire de dilbert, et accepter que les ordinateurs, si cool et génial, ont des limites. Dans votre cas précis, il ne s'agit pas de "cacher" le problème, parce que vous avez dit de ne pas. La langue (l'ordinateur) fournit des solutions de rechange pour le format, que vous n'avez pas à choisir. Vous avez choisi le double, qui a certains avantages sur la virgule, et certains inconvénients. Maintenant, connaissant la réponse, tu es en colère que les inconvénients ne disparaissent pas comme par magie.

En tant que programmeur, vous êtes responsable pour cacher cette baisse de la part des gestionnaires, et il y a beaucoup de façons de le faire. Cependant, les responsables de C# ont la responsabilité de mettre à virgule flottante travail correctement, et de corriger virgule flottante va parfois fausser les calculs.

Ce sera chaque autre nombre moyen de stockage, que nous n'avons pas infinie bits. Notre travail en tant que programmeurs est de travailler avec des ressources limitées pour faire refroidir les choses se passent. Ils ont obtenu de 90% du chemin, juste obtenir le flambeau à la maison.

15voto

Keith Points 46288

Et 0,69 peut facilement être représenté dans binaire, un nombre binaire pour les 69 et un autre pour désigner la position de l' décimal place.

Je pense que c'est une erreur commune - que vous pensez de nombres en virgule flottante comme si ils sont en base 10 (j'.e décimale d'où mon accent).

Oui - vous êtes en train de penser qu'il existe deux nombres entiers parties à cette double: 69 et diviser par 100 pour obtenir le nombre de décimales à se déplacer - qui peut aussi être exprimé comme:
69 x 10 puissance -2.

Cependant flotteurs de stocker la position du point " comme en base 2.

Votre flotteur est stockée en tant que:
68999999999999995 x 2 à la puissance d'un grand nombre négatif

Ce n'est pas tant un problème une fois que vous avez l'habitude de le - la plupart des gens se connaissent et s'attendre à ce que 1/3 ne peut pas être exprimé avec précision en virgule ou en pourcentage. C'est juste que les fractions qui peuvent être exprimées en base 2 sont différents.

11voto

Clifford Points 29933

mais pourquoi ne pas le cadre de travail autour de cela et cacher ce problème, de moi et de me donner la bonne réponse,0.69!!!

Parce que vous lui avez dit d'utiliser binaire à virgule flottante, et la solution est d'utiliser de virgule flottante, donc, vous suggérez que le cadre ne doit pas tenir compte du type que vous avez spécifié et l'utilisation de décimales au lieu de cela, ce qui est beaucoup plus lent, car il n'est pas directement mis en œuvre dans le matériel.

Une solution plus efficace est de ne pas afficher la totalité de la valeur de la représentation et de spécifier explicitement la précision requise par votre sortie. Si vous le format de sortie à deux décimales, vous verrez le résultat que vous attendez. Toutefois, si ce est une application financière décimal est précisément ce que vous devez utilisez - vous l'avez vu Superman III (Espace Bureau) n'avez-vous pas ;)

Notez que tout est fini approximation d'une portée infinie, c'est simplement que la virgule et le double utiliser un autre ensemble d'approximations. L'avantage de la virgule est-il produit les mêmes approximations que vous le feriez si vous étiez en effectuant le calcul vous-même. Par exemple, si vous avez calculé 1/3, finira par arrêter d'écrire 3 quand il a été "suffisamment bonne".

8voto

erikkallen Points 16601

Pour la même raison, 1/3 dans un système décimal apparaît comme 0.33333333333333333333333333333333333333333 et non la fraction exacte, qui est infiniment longue.

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