2009-11-22 4 views
2

Je suis tombé sur quelque chose d'étrange, ici, et je ne sais pas - j'ai le sentiment que cela a quelque chose à voir avec la précision flottante, mais je suis surpris que Python n'affiche pas l'erreur d'approximation.Y a-t-il une précision dans ce nombre que Python ne me montre pas?

Je travaille actuellement sur Project Euler problem 62. Comme un simple test (j'ai depuis résolu en utilisant une approche différente), j'avais un is_cube que j'avais l'intention de vérifier si un nombre de cubes parfaitement. Donc, pour essayer l'échantillon donné, je l'ai fait:

def is_cube(i): 
    c = i ** (1./3) 
    print "c is", c 

Quand je courais cela avec i = 41063625, le résultat attendu était la suivante:

c is 345.0 

est ici où l'inattendu se produisit:

def is_cube(i): 
    c = i ** (1./3) 
    print "c is", int(c) 

Tout à coup, j'avais ceci:

c is 344 

La valeur c ne se compare pas à mon littéral 345.0, soit - c < 345.0 est True.

Y at-il une précision dans ce nombre que Python ne me montre pas? Je me rappelle avoir lu au sujet d'un changement pour rendre les flotteurs semblent plus sains lorsqu'ils sont imprimés; est-ce ceci? Qu'est-ce qui différencie ces deux cas?

>>> def is_cube(i): 
...  c = i ** (1./3) 
...  print "c is", c 
... 
>>> is_cube(41063625) 
c is 345.0 
>>> 41063625 ** (1./3) 
344.99999999999989 

Edit: avait encore la fenêtre ouverte et a fait ceci:

>>> print _ 
345.0 

Maintenant, je commence à penser que j'aurais su que print était à blâmer.

+1

Je ne suis pas sûr d'où vient la confusion. int() prend la partie FRACTIONNELLE du nombre et en résulte en conséquence. Et comme vous l'avez observé, le calcul en virgule flottante de précision relative est juste cela. –

+1

Err, à quel point de moi. Il prend la partie "ENTIER" et rejette entièrement la partie faction. –

+0

@pst: Lisez attentivement. J'ai été trompé par '__str__' en pensant que' c' était '> = 345.0' alors qu'en fait ce n'était pas le cas, il y avait une erreur d'approximation. Par conséquent, je m'attendais à ce que 'int (c)' soit '345', pas' 344'. C'est juste '__str__' qui prend le dessus sur moi à 3:24 du matin, et je ne suis pas tout à fait sûr de savoir où est votre confusion non plus? –

Répondre

4

est d'utiliser c.__str__() (alias str(c).):

print "c is", c 

Ce utilise c.__repr__() (alias repr(c).):

>>> C# In the Python shell 

IIRC, __str__ tronque à 10 décimales, alors que __repr__ va plus loin . Pour obtenir le même comportement que dans le shell Python, vous pouvez faire:

print repr(c) 
# Or 
print "%r" % c 
# Or 
print "%.16f" % c 

Le changement que vous parlez dans votre message est seulement Python 3.1 et ne modifient pas la précision de la sortie: l'algorithme de Gay qui est utilisé pour __repr__ sur les nombres à virgule flottante dans Python 3.1, lorsque deux choix de représentation donnent la même valeur à virgule flottante (comme 0.2 et 0.2000000000000001), choisissez le plus court.

+0

Ah, merci d'avoir clarifié le changement, aussi. Ne détestez pas quand vous lisez quelque chose qui pourrait être pertinent à distance, le fichier, et plus tard, votre mémoire à long terme commence à aller * hé! Hey! Je le sais! * Mais tu ne peux pas te souvenir pourquoi? –

0
print "c is", int(c) 

La conversion entière supprimaient quoi que ce soit après la virgule, même si vous avez 344,99999999999989 il sera toujours arrondir vers le bas. vous pouvez utiliser la vieille école d'impression%

print'c is %5.0f' % c 

ou vous pouvez utiliser tour si vous voulez un entier

print'c is %d' % round(c,0) 

Aussi, vous pourriez être intéressé par d'autres solutions pour le problème de racine cubique here

+1

Si vous allez moins au moins indiquer la raison – 10ToedSloth

+0

Acclamations Craig, mais toujours curieux au sujet du vote vers le bas. Je voudrais savoir pourquoi quelqu'un pensait que ma réponse était si fausse. Donc, si quelqu'un a des critiques constructives, c'est apprécié. – 10ToedSloth

+0

Je suis celui qui a downvoted: votre réponse n'apporte rien que l'OP ne connaissait pas, le problème était sur la précision de 'str', etc. et non sur le point flottant que l'OP semble connaître. –

Questions connexes