Question

J'ai un problème avec le module sur un nombre à virgule flottante en Python.Ce code :

...
print '(' + repr(olddir) + ' + ' + repr(self.colsize) + ') % (math.pi*2) = ' + repr((olddir+self.colsize)
...

Impressions :

(6.281876310240881 + 0.001308996938995747) % (math.pi*2) = 2.9043434324194095e-13

Je sais que les nombres à virgule flottante ne sont pas précis.Mais je n'arrive pas à donner un sens à cela.

Je ne sais pas si c'est lié d'une manière ou d'une autre, mais Google Calculator ne peut pas non plus gérer ce calcul.Voici le résultat de la calculatrice Google :

(6.28187631024 + 0.001308996939) % (pi * 2) = 6.28318531

Quelle est la cause de cette erreur de calcul ?Et comment puis-je l’éviter dans mon programme Python ?

Était-ce utile?

La solution

En utilisant str() imprimer un nombre à virgule flottante imprime en fait une version arrondie du nombre :

>>> print repr(math.pi)
3.1415926535897931
>>> print str(math.pi)
3.14159265359

Nous ne pouvons donc pas vraiment reproduire vos résultats, car nous ne connaissons pas les valeurs exactes avec lesquelles vous effectuez le calcul.Évidemment, la valeur exacte de olddir+self.colsize est légèrement supérieur à 2*math.pi, alors que la somme des valeurs arrondies que vous avez utilisées dans la Calculatrice Google est légèrement inférieure à 2*math.pi.

Autres conseils

La différence entre str et repr

>>> import scipy
>>> pi = scipy.pi
>>> str(pi)
'3.14159265359'
>>> repr(pi)
'3.1415926535897931'

str tronque les nombres à virgule flottante à 12 chiffres, où repr donne la représentation interne (sous forme de chaîne).

MODIFIER:Donc en résumé, le problème est survenu parce que vous avez arrondi prématurément et que vous calculez le module de quelque chose via un nombre qui en est très proche.Avec les nombres à virgule flottante, l'arrondi est inévitablement impliqué dans la conversion des nombres décimaux en binaires.

Tout d’abord, donnez un exemple de la façon dont l’arrondi vous nuit avec les mathématiques réelles (et non les mathématiques à virgule flottante).Regardez (3,14+3,14) % (3,14+3,14), qui est évidemment nul.Maintenant, que se passerait-il si nous arrondissions d’abord les chiffres à un chiffre décimal d’un côté ?Eh bien (3,1+3,1) % (3,14+3,14) = 6,2 % (6,28) = 6,2 (ce que Google vous a donné).Ou si vous avez fait round(3.14159,5) + round(3.14159,5) % (3.14159 + 3.14159) = 6.2832 % 6.28318 = 2e-5.

Donc en arrondissant à N chiffres (en utilisant str qui arrondit effectivement les nombres), votre calcul n'est précis qu'à moins de N chiffres.Pour que ce travail avance, il est nécessaire de forcer l'arrondi à un chiffre supérieur (en gardant deux chiffres calculés pour des raisons de sécurité).Par exemple, str arrondit au chiffre 12, alors peut-être devrions-nous arrondir au chiffre 10.

>>> round(6.28187631024 + 0.001308996939,10) % (round(pi * 2,10))
0
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top