python 3.44 float addition bug?

buck workitharder at gmail.com
Mon Jun 23 20:55:50 EDT 2014


It used to be that the best way to compare floating point numbers while disregarding the inherent epsilon was to use `str(x) == str(y)`. It looks like that workaround doesn't work anymore in 3.4.

What's the recommended way to do this now?

>>> format(.01 + .01 + .01 + .01 + .01 + .01, 'g') == format(.06, 'g')
True


On Saturday, June 21, 2014 12:24:24 PM UTC-7, Ned Deily wrote:
> In article 
> 
> <CAPTjJmrkPd5K__h9Qg12Q+AraFZVaN6eGUdTmEDGe2ccAqEmRw at mail.gmail.com>,
> 
>  Chris Angelico <rosuav at gmail.com> wrote:
> 
> > Also, when you're looking at how things print out, consider looking at
> 
> > two things: the str() and the repr(). Sometimes just "print(p)"
> 
> > doesn't give you all the info, so you might instead want to write your
> 
> > loop thus:
> 
> > 
> 
> > z = 0.01
> 
> > p = 0.0
> 
> > for i in range(19):
> 
> >     p += z
> 
> >     print(str(p) + " -- " + repr(p)) 
> 
> > Sometimes you can get extra clues that way, although in this instance
> 
> > I think you won't.
> 
> 
> 
> Actually, I think this is one case where you would get extra clues (or 
> 
> extra headscratching) if you run the code with various releases of 
> 
> Python.
> 
> 
> 
> $ python2.6 b.py
> 
> 0.01 -- 0.01
> 
> 0.02 -- 0.02
> 
> 0.03 -- 0.029999999999999999
> 
> 0.04 -- 0.040000000000000001
> 
> 0.05 -- 0.050000000000000003
> 
> 0.06 -- 0.060000000000000005
> 
> 0.07 -- 0.070000000000000007
> 
> 0.08 -- 0.080000000000000002
> 
> 0.09 -- 0.089999999999999997
> 
> 0.1 -- 0.099999999999999992
> 
> 0.11 -- 0.10999999999999999
> 
> 0.12 -- 0.11999999999999998
> 
> 0.13 -- 0.12999999999999998
> 
> 0.14 -- 0.13999999999999999
> 
> 0.15 -- 0.14999999999999999
> 
> 0.16 -- 0.16
> 
> 0.17 -- 0.17000000000000001
> 
> 0.18 -- 0.18000000000000002
> 
> 0.19 -- 0.19000000000000003
> 
> 
> 
> $ python2.7 b.py
> 
> 0.01 -- 0.01
> 
> 0.02 -- 0.02
> 
> 0.03 -- 0.03
> 
> 0.04 -- 0.04
> 
> 0.05 -- 0.05
> 
> 0.06 -- 0.060000000000000005
> 
> 0.07 -- 0.07
> 
> 0.08 -- 0.08
> 
> 0.09 -- 0.09
> 
> 0.1 -- 0.09999999999999999
> 
> 0.11 -- 0.10999999999999999
> 
> 0.12 -- 0.11999999999999998
> 
> 0.13 -- 0.12999999999999998
> 
> 0.14 -- 0.13999999999999999
> 
> 0.15 -- 0.15
> 
> 0.16 -- 0.16
> 
> 0.17 -- 0.17
> 
> 0.18 -- 0.18000000000000002
> 
> 0.19 -- 0.19000000000000003
> 
> 
> 
> $ python3.4 b.py
> 
> 0.01 -- 0.01
> 
> 0.02 -- 0.02
> 
> 0.03 -- 0.03
> 
> 0.04 -- 0.04
> 
> 0.05 -- 0.05
> 
> 0.060000000000000005 -- 0.060000000000000005
> 
> 0.07 -- 0.07
> 
> 0.08 -- 0.08
> 
> 0.09 -- 0.09
> 
> 0.09999999999999999 -- 0.09999999999999999
> 
> 0.10999999999999999 -- 0.10999999999999999
> 
> 0.11999999999999998 -- 0.11999999999999998
> 
> 0.12999999999999998 -- 0.12999999999999998
> 
> 0.13999999999999999 -- 0.13999999999999999
> 
> 0.15 -- 0.15
> 
> 0.16 -- 0.16
> 
> 0.17 -- 0.17
> 
> 0.18000000000000002 -- 0.18000000000000002
> 
> 0.19000000000000003 -- 0.19000000000000003
> 
> 
> 
> What's going on here is that in Python 2.7 the repr() of floats was 
> 
> changed to use the minimum number of digits to accurately roundtrip the 
> 
> number under correct rounding.  For compatibility reasons, the str() 
> 
> representation was not changed for 2.7.  But in Python 3.2, str() was 
> 
> changed to be identical to repr() for floats.  It's important to keep in 
> 
> mind that the actual binary values stored in float objects are the same 
> 
> across all of these releases; only the representation of them as decimal 
> 
> characters varies.
> 
> 
> 
> https://docs.python.org/2.7/whatsnew/2.7.html#other-language-changes
> 
> 
> 
> http://bugs.python.org/issue9337
> 
> 
> 
> -- 
> 
>  Ned Deily,
> 
>  nad at acm.org



More information about the Python-list mailing list