Python -- floating point arithmetic

David Mainzer dm at tu-clausthal.de
Thu Jul 8 08:16:36 EDT 2010


On 07/07/2010 08:08 PM, Raymond Hettinger wrote:
> On Jul 7, 5:55 am, Mark Dickinson <dicki... at gmail.com> wrote:
>> On Jul 7, 1:05 pm, david mainzer <d... at 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:
>>
>>> dm at 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


Thanks to all for your help :)

All your comments helped me and now i know how it works in python !

Best
David



More information about the Python-list mailing list