msg59113 - (view) |
Author: Guido van Rossum (gvanrossum) *  |
Date: 2008-01-03 00:04 |
Since 1e-1000 == 0.0 (on an IEEE-754 platform anyway), I would expect -1e-1000 to be -0.0. But it does not appear that way: >>> 1e-1000 0.0 >>> -0.0 -0.0 >>> -1e-1000 0.0 However (correctly): >>> (-1.0) * 1e-1000 -0.0 >>> -(1e-1000) -0.0 I suspect the optimization for -x where x is a float literal is incorrectly triggering here. |
|
|
msg59114 - (view) |
Author: Guido van Rossum (gvanrossum) *  |
Date: 2008-01-03 00:07 |
BTW this was on x86 Linux. On x86 OSX (10.4, Tiger) it works correctly: >>> -1e-1000 -0.0 |
|
|
msg59120 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2008-01-03 03:05 |
Tracing the calls through ast_for_factor -> ast_for_atom -> parsenumber -> PyOS_ascii_atof -> PyOS_ascii_strtod -> strtod, it looks as though the cause is simply that strtod behaves differently on the two platforms. I get that the following code: #include <stdio.h> #include <stdlib.h> int main() { char *fail_pos; double x; x = strtod("-1e-1000", &fail_pos); printf("Result: %f\n", x); return 0; } produces 0.000000 on Linux (SuSE 10.2) and -0.000000 on OS X 10.4.11. |
|
|
msg59132 - (view) |
Author: Christian Heimes (christian.heimes) *  |
Date: 2008-01-03 15:25 |
I think we have found a bug in glibc's math code. I'm hanging around in #glibc and see if I can get an opinion on the matter. |
|
|
msg59133 - (view) |
Author: Christian Heimes (christian.heimes) *  |
Date: 2008-01-03 15:29 |
On Windows -1E-1000 returns 0.0, too. We may need to fix it in your own code and set the sign bit ourself. |
|
|
msg59135 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2008-01-03 16:05 |
Presumably float('-1e-1000') should also give -0. (?) If so, then it looks as though the fix ought to go in PyOS_ascii_strtod: one obvious possibility would be to replace any leading '-' sign by a '+' sign before calling the system strtod, then negate the result afterwards. |
|
|
msg59148 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2008-01-03 19:45 |
Here's a possible fix for this issue; it parses a number by first stripping leading whitespace and any sign, then passing the remaining string to the system strtod. This patch also fixes another bug in pystrtod.c, where ValueError is not raised on a hex float with a leading + sign: >>> float('0x3') Traceback (most recent call last): File "", line 1, in ValueError: invalid literal for float(): 0x3 >>> float('+0x3') # expect ValueError 3.0 |
|
|
msg59273 - (view) |
Author: Guido van Rossum (gvanrossum) *  |
Date: 2008-01-05 01:02 |
Committed revision 59725. Thanks for the fix, Mark! This issue is a great example of how our development process works well. I propose not to backport this to 2.5.2, it's a rather minor issue and who knows what user code might depend on the existing buggy behavior... |
|
|
msg59274 - (view) |
Author: Guido van Rossum (gvanrossum) *  |
Date: 2008-01-05 01:02 |
PS. I reformatted some long lines in the patch. In general, I like to keep all lines < 80 chars, in both C and Python code. |
|
|