[Python-Dev] Round Bug in Python 1.6?
Guido van Rossum
guido@python.org
Fri, 07 Apr 2000 15:35:32 -0400
> Tim Peters wrote:
> > The best possible IEEE-754 double approximation to 3.1416 is (exactly)
> >
> > 3.141599999999999948130380289512686431407928466796875
>
> Let's call this number 'A' for the sake of discussion.
>
> > so the output you got is correctly rounded to 17 significant digits. IOW,
> > it's a feature.
>
> Clearly there is something very wrong here:
>
> Python 1.5.2+ (#2, Mar 28 2000, 18:27:50)
> Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
> >>> 3.1416
> 3.1415999999999999
> >>>
>
> Now you say that 17 significant digits are required to ensure
> that eval(repr(x)) == x, but we surely know that 17 digits are
> *not* required when x is A because i *just typed in* 3.1416 and
> the best choice of double value was A.
Ping has a point!
> I haven't gone and figured it out, but i'll take your word for
> it that 17 digits may be required in *certain* cases to ensure
> that eval(repr(x)) == x. They're just not required in all cases.
>
> It's very jarring to type something in, and have the interpreter
> give you back something that looks very different. It breaks a
> fundamental rule of consistency, and that damages the user's
> trust in the system or their understanding of the system. (What
> do you do then, start explaining the IEEE double representation
> to your CP4E beginner?)
>
> What should really happen is that floats intelligently print in
> the shortest and simplest manner possible, i.e. the fewest
> number of digits such that the decimal representation will
> convert back to the actual value. Now you may say this is a
> pain to implement, but i'm talking about sanity for the user here.
>
> I haven't investigated how to do this best yet. I'll go off
> now and see if i can come up with an algorithm that's not
> quite so stupid as
>
> def smartrepr(x):
> p = 17
> while eval('%%.%df' % (p - 1) % x) == x: p = p - 1
> return '%%.%df' % p % x
Have a look at what Java does; it seems to be doing this right:
& jpython
JPython 1.1 on java1.2 (JIT: sunwjit)
Copyright (C) 1997-1999 Corporation for National Research Initiatives
>>> import java.lang
>>> x = java.lang.Float(3.1416)
>>> x.toString()
'3.1416'
>>> ^D
&
Could it be as simple as converting x +/- one bit and seeing how many
differing digits there were? (Not that +/- one bit is easy to
calculate...)
--Guido van Rossum (home page: http://www.python.org/~guido/)