[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:
>[Smith]
>>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
>False
>
BTW, for the OP, chasing minimum float values is probably best done with powers of 2
>>> math.ldexp(1, -1074)
4.9406564584124654e-324
>>> math.ldexp(1, -1075)
0.0
>>> .5**1074
4.9406564584124654e-324
>>> .5**1075
0.0
>>> math.frexp(.5**1074)
(0.5, -1073)
>>> math.frexp(.5**1075)
(0.0, 0)
Regards,
Bengt Richter
More information about the Python-Dev
mailing list