Re: [Python-Dev] small floating point number problem
Smith [EMAIL PROTECTED] 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 There are all sorts of ugly bits when working with all binary fp numbers (for the small ones, look for a reference on 'denormals'). I'm sure that Raymond has more than a few things to say about them (and fp in general), but I will speed up the discussion by saying that you should read the IEEE 754 standard for floating point, or alternatively ask on comp.lang.python where more users would get more out of the answers that you will recieve there. One thing to remember is that decimal is not the native representation of binary floating point, so 1e-100 differs from 1e-101 significantly in various bit positions. You can use struct.pack('d', flt) to see this, or you can try any one of the dozens of IEEE 754 javascript calculators out there. - Josiah ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] small floating point number problem
[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 Raymond ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] small floating point number problem
On Wed, 08 Feb 2006 03:08:25 -0500, Raymond Hettinger [EMAIL PROTECTED] 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 ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] small floating point number problem
[Raymond Hettinger] ... 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: Just noting that such behavior is a violation of the 754 standard for string-double conversion. But Microsoft's libraries don't _claim_ to support the 754 standard, so good luck suing them ;-). Python doesn't promise anything here either. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] small floating point number problem
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 a==0 True-- it really is 0; this is not a repr issue b=.1*1e-307 b 9.9991e-309 a==b False--they really are different Also, I see that there is some graininess in the numbers at the low end, but I'm guessing that there is some issue with floating points that I would need to read up on again. The above dilemma is a little more troublesome. m=2.470328229206234e-017 s=1e-307 m*s 4.9406564584124654e-324 #2x too large 2*m*s 4.9406564584124654e-324 3*m*s==4*m*s True /c ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com