Je sais que les erreurs d'arrondi se produisent dans l'arithmétique à virgule flottante, mais quelqu'un peut-il expliquer la raison de celle-ci ?
>>> 8.0 / 0.4 # as expected
20.0
>>> floor(8.0 / 0.4) # int works too
20
>>> 8.0 // 0.4 # expecting 20.0
19.0
Cela se produit avec Python 2 et 3 sur x64.
D'après ce que je vois, il s'agit soit d'un bogue, soit d'une spécification très stupide de l'outil de gestion de l'environnement. //
car je ne vois pas pourquoi la dernière expression devrait être évaluée à 19.0
.
Pourquoi n'est-ce pas a // b
simplement défini comme floor(a / b)
?
EDIT : 8.0 % 0.4
évalue également à 0.3999999999999996
. Au moins cela est conséquent puisque alors 8.0 // 0.4 * 0.4 + 8.0 % 0.4
évalue à 8.0
EDIT : Il ne s'agit pas d'un duplicata de Les maths à virgule flottante sont-elles cassées ? puisque je demande pourquoi cette opération spécifique est sujette à des erreurs d'arrondi (peut-être évitables), et pourquoi a // b
n'est pas défini comme / égal à floor(a / b)
REMARK : Je suppose que la raison profonde pour laquelle cela ne fonctionne pas est que la division de plancher est discontinue et a donc une infinité. numéro de condition ce qui en fait un problème mal posé. La division de plancher et les nombres à virgule flottante sont fondamentalement incompatibles et vous ne devriez jamais utiliser la fonction //
sur les flottants. Utilisez simplement des entiers ou des fractions à la place.
3 votes
C'est intéressant,
'%.20f'%0.4
donne'0.40000000000000002220'
donc0.4
est apparemment juste un peu plus0.4
.2 votes
@khelwood comment
floor(8.0/0.4)
produisent des résultats corrects ?1 votes
@AswinMurugesh Je ne sais pas ; c'est pourquoi je n'ai pas publié de réponse à cette question.
2 votes
Tout d'abord, les nombres à virgule flottante avec le
float
sont généralement erronées. Deuxièmement,//
et%
sont assez peu fiables (c'est-à-dire qu'ils ont un comportement inattendu) avec des nombres négatifs et desfloat
les chiffres. Le site documentation sur les objets décimaux discute brièvement//
avec des nombres entiers négatifs et comment leDecimal
La bibliothèque le traite différemment.1 votes
@TigerhawkT3 Ouais, eh bien
%
et//
sont généralement inscrits sous la forme entier opérations. Dans tous les cas, notez quex = 8.0;y=0.4;q = x//y; r = x%y
tout en respectant la loi :q*y+r == x
qui est la propriété que vous voulez de//
et%
. Malheureusementmath
n'a aucun moyen de calculer le reste, donc si vous choisissezq = math.floor(x/y)
vous n'avez pas de moyen intégré pour trouver uner
qui satisfont à cette propriété.0 votes
N'utilisez pas la virgule flottante pour un calcul exact.
0 votes
La vraie surprise, pour moi, c'est que
8 / 0.4 != 8.0 // 0.4
dans Python 2.7. J'avais pensé qu'une partie de la raison de l'utilisation de l'option//
était de préserver le comportement de l'opérateur Python 2./
pour la compatibilité avec Python 3, en tant qu'opérateur distinct implémenté dans les versions 2 et 3.3 votes
Duplicata possible de Les mathématiques à virgule flottante sont-elles cassées ?
3 votes
@AlexanderVogt Pas vraiment, n'est-ce pas ? La question n'est pas de savoir pourquoi les résultats en virgule flottante ne sont pas exacts, mais plutôt pourquoi python fait deux choses différentes pour
floor(8.0/0.4)
et la "division de l'étage"8.0//0.4
.0 votes
PEP 238 déclare que
a // b == floor(a/b)
. Je pense que le PEP est bogué, ou du moins ambigu. Aussi,8.0 / 0.4 < 20.0 == False
. Je n'arrive pas à comprendre pourquoi cela est considéré comme une sortie souhaitable pour//
avec deux arguments flottants.