Question

Pourquoi ce 7.30 - 7.20 code en Ruby retourne 0.0999999999999996, pas 0.10?

Mais si je vais écrire 7.30 - 7.16, par exemple, tout sera ok, je vais 0.14.

Qu'est-ce que le problème, et comment puis-je résoudre?

Était-ce utile?

Autres conseils

Le problème est que quelques chiffres, nous pouvons facilement écrire en décimal ne sont pas une représentation exacte dans le format de point de Floating particulier mis en oeuvre par le matériel actuel. Une façon décontractée de dire est que tous les entiers font, mais pas toutes les fractions, parce que nous enregistrons normalement la fraction avec un exposant de 2**e. Donc, vous avez 3 choix:

  1. Arrondir appropriée. Le résultat est toujours unrounded vraiment très proche, donc un résultat arrondi est toujours « parfait ». C'est ce que Javascript fait et beaucoup de gens ne réalisent même pas que JS fait tout en virgule flottante.

  2. Utilisez arithmétique à virgule fixe. Ruby fait réellement ce vraiment facile; il est l'une des seules langues qui se déplace de façon transparente à la classe Bignum de Fixnum que les numéros grossissent.

  3. Utilisez une classe qui est conçu pour résoudre ce problème, comme BigDecimal

Pour regarder le problème plus en détail, nous pouvons essayer de représenter votre « 7.3 » en binaire. La partie 7 est facile, 111, mais comment pouvons-nous faire 0,3? 111,1 est 7.5, trop grand, 111,01 est 7,25, se rapprocher. Fin de compte, 111,010011 est le « côté plus petit nombre le plus proche », 7,296875, et quand nous essayons de remplir le 0,003125 manquant finalement, nous voyons que c'est juste 111,010011001100110011 ... pour toujours, pas représentable dans notre encodage choisi dans une chaîne de bits finie .

Le problème est que virgule flottante est inexact . Vous pouvez le résoudre en utilisant des entiers rationnels, BigDecimal ou tout simplement (par exemple si vous voulez stocker de l'argent, vous pouvez stocker le nombre de cents comme un entier au lieu du nombre de dollars comme un flotteur).

BigDecimal peut stocker avec précision un nombre qui a un nombre fini de chiffres dans les numéros de base 10 et tours qui ne sont pas (pour trois tiers ne sont pas un tout).

rationnel peut stocker avec précision un nombre rationnel et ne peut pas stocker des nombres irrationnels du tout.

C'est une erreur commune de la façon dont le nombre de points de flotteur sont représentés dans la mémoire.

Utilisez BigDecimal si vous avez besoin des résultats exacts.

result=BigDecimal.new("7.3")-BigDecimal("7.2")
puts "%2.2f" % result

Il est intéressant de noter qu'un certain nombre qui a quelques décimales dans une base peut généralement avoir un très grand nombre de décimales dans une autre. Par exemple, il faut un nombre infini de décimales pour exprimer 1/3 (= 0,3333 ...) dans la base 10, mais seulement une décimale dans la base 3. De même, il faut beaucoup de décimales pour exprimer le nombre 1/10 ( = 0,1) dans la base 2.

Puisque vous faites des maths à virgule flottante alors le nombre de retour est ce que votre ordinateur utilise pour la précision.

Si vous voulez une réponse plus proche, avec une précision de jeu, juste multiple du flotteur par cette (comme 100), le convertir en un entier, faites le calcul, puis diviser.

Il existe d'autres solutions, mais je trouve que ce soit le plus simple puisque l'arrondissement semble toujours un peu hasardeux pour moi.

a été posée ici, vous voudrez peut-être chercher quelques-unes des réponses données avant, comme celui-ci: Faire face à des problèmes de précision en nombres à virgule flottante

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top