2009-08-23 7 views
60

Je crée un programme qui, pour des raisons qui n'ont pas besoin d'être expliquées, nécessite la conversion d'un flottant en une chaîne à compter avec len(). Cependant, str (float (x)) fait que x est arrondi quand il est converti en une chaîne, ce qui rejette l'ensemble. Est-ce que quelqu'un sait d'un correctif pour cela? Voici le code utilisé si vous voulez savoir:Conversion d'un flottant en une chaîne sans arrondi

len(str(float(x)/3)) 
+2

si x est à l'origine str, pourquoi le casting? –

+1

-1: Aucun exemple de sortie requise pour différentes valeurs de 'x'. Sans exemples, nous ne pouvons que deviner quel est le problème. –

Répondre

92

Une certaine forme de l'arrondissement est souvent inévitable lorsqu'ils traitent avec des nombres à virgule flottante. C'est parce que les nombres que vous pouvez exprimer exactement dans la base 10 ne peuvent pas toujours être exprimés exactement dans la base 2 (que votre ordinateur utilise).

Par exemple:

>>> .1 
0.10000000000000001 

Dans ce cas, vous voyez .1 converti en une chaîne en utilisant repr:

>>> repr(.1) 
'0.10000000000000001' 

Je crois côtelettes de python hors les derniers chiffres lorsque vous utilisez str() afin de contourner ce problème, mais il s'agit d'une solution de contournement partielle qui ne remplace pas pour comprendre ce qui se passe.

>>> str(.1) 
'0.1' 

Je ne sais pas exactement quels problèmes vous causent "l'arrondi". Peut-être que vous feriez mieux avec la mise en forme de chaîne comme un moyen de contrôler plus précisément votre sortie?

par exemple.

>>> '%.5f' % .1 
'0.10000' 
>>> '%.5f' % .12345678 
'0.12346' 

Documentation here.

10
len(repr(float(x)/3)) 

Cependant, je dois dire que ce n'est pas aussi fiable que vous pensez.

Les flottants sont entrés/affichés sous forme de nombres décimaux, mais votre ordinateur (en fait, votre bibliothèque C standard) les stocke en tant que binaire. Vous obtenez des effets secondaires de cette transition:

>>> print len(repr(0.1)) 
19 
>>> print repr(0.1) 
0.10000000000000001 

L'explication sur la raison pour laquelle cela se produit est dans this chapter du tutoriel python.

Une solution serait d'utiliser un type qui suit spécifiquement les nombres décimaux, comme ceux decimal.Decimal python:

>>> print len(str(decimal.Decimal('0.1'))) 
3 
+3

+1 pour la décimale. –

+0

Bon article sur la façon de travailler avec les résultats de flottement de la division: https://stackoverflow.com/questions/2958684/python-division – Trutane

3

D'autres réponses ont déjà souligné que la représentation des nombres flottants est une question épineuse, c'est le moins qu'on puisse dire.

Puisque vous ne donnez pas assez de contexte dans votre question, je ne peux pas savoir si le module décimal peut être utile pour vos besoins:

http://docs.python.org/library/decimal.html

entre autres choses que vous pouvez spécifier explicitement la précision que vous souhaite obtenir (des docs):

>>> getcontext().prec = 6 
>>> Decimal('3.0') 
Decimal('3.0') 
>>> Decimal('3.1415926535') 
Decimal('3.1415926535') 
>>> Decimal('3.1415926535') + Decimal('2.7182818285') 
Decimal('5.85987') 
>>> getcontext().rounding = ROUND_UP 
>>> Decimal('3.1415926535') + Decimal('2.7182818285') 
Decimal('5.85988') 

Un simple exemple de mon invite (python 2.6):

>>> import decimal 
>>> a = decimal.Decimal('10.000000001') 
>>> a 
Decimal('10.000000001') 
>>> print a 
10.000000001 
>>> b = decimal.Decimal('10.00000000000000000000000000900000002') 
>>> print b 
10.00000000000000000000000000900000002 
>>> print str(b) 
10.00000000000000000000000000900000002 
>>> len(str(b/decimal.Decimal('3.0'))) 
29 

Peut-être que cela peut aider? décimal est en python stdlib depuis 2.4, avec des ajouts en python 2.6.

Hope this helps, Francesco

Questions connexes