On Jul 7, 5:55 am, Mark Dickinson <dicki...@gmail.com> wrote: > On Jul 7, 1:05 pm, david mainzer <d...@tu-clausthal.de> wrote: > > > > > Dear Python-User, > > > today i create some slides about floating point arithmetic. I used an > > example from > > >http://docs.python.org/tutorial/floatingpoint.html > > > so i start the python shell on my linux machine: > > > d...@maxwell $ python > > Python 2.6.5 (release26-maint, May 25 2010, 12:37:06) > > [GCC 4.3.4] on linux2 > > Type "help", "copyright", "credits" or "license" for more information.>>> > > >>> sum = 0.0 > > >>> >>> for i in range(10): > > > ... sum += 0.1 > > ...>>> >>> sum > > 0.99999999999999989 > > > But thats looks a little bit wrong for me ... i must be a number greater > > then 1.0 because 0.1 = > > 0.100000000000000005551115123125782702118158340454101562500000000000 > > in python ... if i print it.
[Mark Dickinson] > So you've identified one source of error here, namely that 0.1 isn't > exactly representable (and you're correct that the value stored > internally is actually a little greater than 0.1). But you're > forgetting about the other source of error in your example: when you > do 'sum += 0.1', the result typically isn't exactly representable, so > there's another rounding step going on. That rounding step might > produce a number that's smaller than the actual exact sum, and if > enough of your 'sum += 0.1' results are rounded down instead of up, > that would easily explain why the total is still less than 1.0. One key for understanding floating point mysteries is to look at the actual binary sums rather that their approximate representation as a decimal string. The hex() method can make it easier to visualize Mark's explanation: >>> s = 0.0 >>> for i in range(10): ... s += 0.1 ... print s.hex(), repr(s) 0x1.999999999999ap-4 0.10000000000000001 0x1.999999999999ap-3 0.20000000000000001 0x1.3333333333334p-2 0.30000000000000004 0x1.999999999999ap-2 0.40000000000000002 0x1.0000000000000p-1 0.5 0x1.3333333333333p-1 0.59999999999999998 0x1.6666666666666p-1 0.69999999999999996 0x1.9999999999999p-1 0.79999999999999993 0x1.cccccccccccccp-1 0.89999999999999991 0x1.fffffffffffffp-1 0.99999999999999989 Having used hex() to understand representation error (how the binary partial sums are displayed), you can use the Fractions module to gain a better understanding of rounding error introduced by each addition: >>> s = 0.0 >>> for i in range(10): exact = Fraction.from_float(s) + Fraction.from_float(0.1) s += 0.1 actual = Fraction.from_float(s) error = actual - exact print '%-35s%-35s\t%s' % (actual, exact, error) 3602879701896397/36028797018963968 3602879701896397/36028797018963968 0 3602879701896397/18014398509481984 3602879701896397/18014398509481984 0 1351079888211149/4503599627370496 10808639105689191/36028797018963968 1/36028797018963968 3602879701896397/9007199254740992 14411518807585589/36028797018963968 -1/36028797018963968 1/2 18014398509481985/36028797018963968 -1/36028797018963968 5404319552844595/9007199254740992 21617278211378381/36028797018963968 -1/36028797018963968 3152519739159347/4503599627370496 25220157913274777/36028797018963968 -1/36028797018963968 7205759403792793/9007199254740992 28823037615171173/36028797018963968 -1/36028797018963968 2026619832316723/2251799813685248 32425917317067569/36028797018963968 -1/36028797018963968 9007199254740991/9007199254740992 36028797018963965/36028797018963968 -1/36028797018963968 Hope this helps your slides, Raymond -- http://mail.python.org/mailman/listinfo/python-list