[Python-Dev] small floating point number problem

Bengt Richter bokr at oz.net
Wed Feb 8 16:54:38 CET 2006

On Wed, 08 Feb 2006 03:08:25 -0500, "Raymond Hettinger" <raymond.hettinger at verizon.net> wrote:

>>I just ran into a curious behavior with small floating points, trying to 
>>find the limits of them on my machine (XP). Does anyone know why the '0.0' 
>>is showing up for one case below but not for the other? According to my 
>>tests, the smallest representable float on my machine is much smaller than 
>>1e-308: it is
>> 2.470328229206234e-325
>> but I can only create it as a product of two numbers, not directly. Here 
>> is an attempt to create the much larger 1e-308:
>>>>> a=1e-308
>>>>> a
>> 0.0
>The clue is in that the two differ by 17 orders of magnitude (325-308) which 
>is about 52 bits.
>The interpreter builds 1-e308 by using the underlying C library 
>string-to-float function and it isn't constructing numbers outside the 
>normal range for floats.  When you enter a value outside that range, the 
>function underflows it to zero.
>In contrast, your computed floats (such as 1*1e-307) return a denormal 
>result (where the significand is stored with fewer bits than normal because 
>the exponent is already at its outer limit).  That denormal result is not 
>zero and the C library float-to-string conversion successfully generates a 
>decimal string representation.
>The asymmetric handling of denormals by the atof() and ftoa() functions is 
>why you see a difference.  A consequence of that asymmetry is the breakdown 
>of the expected eval(repr(f))==f invariant:
>>>> f = f = .1*1e-307
>>>> eval(repr(f)) == f
BTW, for the OP, chasing minimum float values is probably best done with powers of 2

 >>> math.ldexp(1, -1074)
 >>> math.ldexp(1, -1075)
 >>> .5**1074
 >>> .5**1075
 >>> math.frexp(.5**1074)
 (0.5, -1073)
 >>> math.frexp(.5**1075)
 (0.0, 0)

Bengt Richter

More information about the Python-Dev mailing list