开发者

Is there precision in this number that Python isn't showing me?

I've run into something odd, here, and I'm at a loss -- I have a feeling this has something to do with floating precision, but I'm surprised Python would not display the approximation error, if so.

I'm working on Project Euler problem 62. As a simple test (I've since solved using a different approach), I had a is_cube which I intended to check if a number cubes perfectly. So, to try the sample given, I did this:

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

When I ran this with i = 41063625, the expected output was:

c is 345.0

Here's where the unexpected happened:

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

Suddenly, I had this:

c is 344

The value c does not compare against my 345.0 literal, either -- c < 345.0 is True.

Is there 开发者_Go百科precision in this number that Python is not showing me? I seem to recall reading about a change to make floats appear more sane when printed; is this it? What is different about these two cases?

>>> 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: Still had the window open and did this:

>>> print _
345.0

Now I'm starting to think I should have known all along that print was to blame.


This is using c.__str__() (aka. str(c)) :

print "c is", c

This is using c.__repr__() (aka. repr(c)) :

>>> c # In the Python shell

IIRC, __str__ truncates to 10 decimals, whereas __repr__ goes further. To get the same behavior as in the Python shell, you could do :

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

The change you're talking about in your message is only about Python 3.1 and do not alter the precision of the output : Gay's algorithm which is used for __repr__ on floating point numbers in Python 3.1 will, when given two representation choices which yields the same floating point value (like 0.2 and 0.2000000000000001), choose the shortest one.


    print "c is", int(c)

The integer conversion will simply drop anything after the decimal point so even if you have 344.99999999999989 it will always round down. you could use old school print %

 print'c is %5.0f' % c

or you could use round if you want an integer

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

Also you might be interested in other solutions for the cube root problem here

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜