0
votes

Calcul de nombres de points flottants et d'erreur dans un certain état de boucle en python

J'essaie de faire une simple boucle en python. La boucle est censée arrêter si d <= 4. Malheureusement, en raison du problème arithmétique de point flottant, le dernier calcul donne au 4.00000000000000001 (au lieu de 4), puis arrêtez la boucle. Existe-t-il une solution simple pour ce type de problème?

entrée xxx

sortie xxx


0 commentaires

3 Réponses :


2
votes

L'impression n'a rien à voir avec les mathématiques à virgule flottante.

Votre boucle p>

  1. tests si d
    1. calcule le nouveau d code> li>
    2. impressions d code> - avec une valeur de li> ol> li> ol>
      0.2
      0.4
      0.6000000000000001
      0.8
      1.0
      1.2000000000000002
      1.4000000000000001
      1.6
      1.8
      2.0
      2.2
      2.4000000000000004
      2.6
      2.8000000000000003
      3.0
      3.2
      3.4000000000000004
      3.6
      3.8000000000000003
      4.0
      


11 commentaires

La position de l'impression n'est pas le problème. Le résultat du dernier calcul est "SUPPOSÉ" d'être 4, puis de passer la condition. Mais c'est déjà plus de 4.


@Patrickartner Si je ne me trompe pas, ce code donne le même résultat. Je peux mettre le impression avant ou après d + = b * c , ce sera le même. J'ai besoin d'arrêter exactement à 4 heures.


@Peteresten est votre question une DUPE de Stackoverflow.com/Questtions/5595425/... ? ... tandis que pas maths.isclose (a, d, rel_tol = 1e-5):


@Patrickartner Oui, sujet similaire. Mais c'est frustrant: il n'y a rien de plus gentil ou plus intuitif que ça? Je n'ai pas ce genre de problème avec PHP par exemple.


@Petersteven Vous pouvez éviter les erreurs d'accumulation - voir Modifier.


@Patrickartner Merci, c'est mieux, mais le problème sera le même si l'état est maintenant de 3,8. La valeur 3.8 vous manquera que je manquante la valeur 4 du code d'origine.


Ma meilleure solution jusqu'à présent est isclose () mais toujours pas satisfaisant complètement.


@Patrickartner, hack par pirate de hack, cela supprime tout problème: d = 10 * b * c * rounds / 10 . Vérifiez: impression (d == 4) # => vrai . Si c = 0,01 , utilisez 100 à la place.


@igian Le Delta ajouté est d'environ 0,2 - votre hack se débarrasse de l'incertitude décimale :) Peut-être poster comme propre réponse


@Pesterestippl Php aura exactement le même problème, il pourrait simplement être «utile» masqué dans certaines situations. Les arithmétiques du point flottant seront Toujours avoir ce "problème", c'est pourquoi numpopy méthodes tels que linspace et arange existe - vous permettant de créer ces machines-précision


d = b * c * ronds peut produire une valeur supérieure ou inférieure à celle souhaitée en raison de l'arrondi, cette solution n'est donc pas correcte.



1
votes

Etant donné que D est supérieur à 4 (légèrement) à la dernière itération, D ne saisit pas la boucle à la prochaine itération et, par conséquent, n'imprime pas le 4.200 (je suppose que vous attendez). Pour résoudre ce problème (ce genre de problèmes), vous pouvez utiliser cette structure tout en faisant des comparaisons. Il suffit de choisir Epsilon selon la précision dont vous avez besoin. XXX

Au lien suivant, on peut trouver une version plus élaborée, générique et élégante pour résoudre ce problème. https://www.learncpp.com/cpp-tutorial/35 -Rélibauté-opérateurs-comparaisons /


1 commentaires

J'ai essayé cela et tu as raison, ça marche. Mais je cherchais quelque chose de plus agréable.



1
votes

Notez que cela n'a rien à voir avec Python en soi. Vous aurez ce problème avec n'importe quelle langue (par exemple, C) qui représente des valeurs de points flottants utilisant IEEE 754 codage ou tout codage binaire similaire. C'est parce que des valeurs décimales comme 0,2 ne peuvent pas être représentées exactement dans un format binaire comme IEEE 754. Si vous «comparez les valeurs de points flottants», vous trouverez de nombreux articles décrivant ce problème et comment y faire face. Par exemple, Celui-ci .

Selon votre situation, vous pouvez mieux vous aider à utiliser quelque chose comme une représentation entière à l'échelle. Par exemple, si vos valeurs ont toujours une précision de 1/10e, l'échelle de la même vitesse de dix: 11 est de 1,1, 38 est de 3,8, etc. Il existe également le module décimal


0 commentaires