6
votes

Arithmétique en rubis

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

Mais si j'écrirai 7.30 - 7.16 , par exemple, tout ira bien, je vais obtenir 0.14 . .

Quel problème, et comment puis-je le résoudre?


0 commentaires

6 Réponses :


1
votes

C'est une erreur courante de la manière dont les numéros de points flottants sont représentés en mémoire.

Utilisez BigDecimal si vous avez besoin de résultats exacts. P>

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


1 commentaires

Notez que BigDecimal ne donne que des résultats exacts si le nombre a un nombre fini de chiffres dans la base 10.



3
votes

Le problème est que Point flottant est inexact . Vous pouvez le résoudre en utilisant des entiers rationnels, bigdecimal ou tout simplement simples (par exemple, si vous souhaitez stocker de l'argent, vous pouvez stocker le nombre de centimes en tant qu'OB au lieu du nombre de dollars en tant que flotteur).

BigDecimal peut stocker avec précision n'importe quel nombre disposant d'un nombre fini de chiffres dans les numéros de base 10 et rounds qui ne le font pas (les trois tiers ne sont pas un tout).

Rational peut stocker avec précision tout numéro rationnel et ne peut pas conserver les numéros irrationnels du tout.


0 commentaires

0
votes

Puisque vous faites des mathématiques de point flottant, le nombre renvoyé est ce que votre ordinateur utilise pour la précision.

Si vous souhaitez une réponse plus étroite, à une précision définie, il suffit de multiplier le flotteur par celui (tel que par 100), convertissez-le en int, faites le calcul, puis divisez-le.

Il y a d'autres solutions, mais je trouve que c'est le plus simple que l'arrondi semble toujours un peu sify pour moi.

Ceci a été demandé avant ici, vous voudrez peut-être rechercher certaines des réponses données précédemment, telles que celle-ci: Traitement des problèmes de précision dans les numéros de points flottants


0 commentaires

20
votes

1 commentaires

À droite. C'est vrai quelle que soit la langue - Java, Ruby, C # Tous "souffrent" de cela. C'est due au choix de la logique binaire et de notre façon de représenter des nombres de points flottants.



6
votes

Le problème est que certains chiffres que nous pouvons facilement écrire en décimal ne disposent pas d'une représentation exacte dans le format point flottant mis en œuvre par le matériel actuel. Un moyen décontracté d'indiquer que tous les entiers font, mais pas toutes les fractions, car nous stockons normalement la fraction avec un 2 ** e exponent. Donc, vous avez 3 choix:

  1. arrondir de manière appropriée. Le résultat non fini est toujours vraiment vraiment proche, un résultat arrondi est invariablement "parfait". C'est ce que JavaScript et beaucoup de gens ne réalisent même pas que JS fait tout dans le point flottant.

  2. Utilisez l'arithmétique de point fixe. Ruby rend vraiment cela vraiment facile; C'est l'une des seules langues qui se déplacent de manière transparente vers la classe Bignum de Fixnum alors que des chiffres deviennent plus gros.

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

    Pour examiner le problème plus en détail, nous pouvons essayer de représenter votre "7,3" en binaire. La 7 partie est facile, 111, mais comment pouvons-nous faire .3? 111.1 est 7,5, trop grand, 111.01 est de 7,25, se rapprocher. Il se trouve, 111.010011 est le "prochain nombre le plus petit le plus proche", 7.296875, et lorsque nous essayons de remplir le manquant .003125 finalement, nous découvrons que c'est seulement 111.010011001100110011 ... pour toujours, pas représentable dans notre codage choisi dans une chaîne de bits finie .


0 commentaires

1
votes

Il est intéressant de noter qu'un chiffre comportant peu de 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 une seule décimale dans la base 3. De même, il faut de nombreuses décimales pour exprimer le nombre 1/10 ( = 0.1) dans la base 2.


0 commentaires