Issue3166
Created on 2008-06-21 21:11 by marketdickinson, last changed 2008-11-06 17:30 by belopolsky.
| msg68545 (view) |
Author: Mark Dickinson (marketdickinson) |
Date: 2008-06-21 21:11 |
|
If n is a Python long, then one might expect float(n) to return the
closest float to n. Currently it doesn't do this. For example (with
Python 2.6, on OS X 10.5.2/Intel):
>>> n = 295147905179352891391L
The closest float to n is equal to n+1. But float(n) returns the
further of the two floats bracketing n, equal to n-65535:
>>> float(n)
2.9514790517935283e+20
>>> long(float(n))
295147905179352825856L
>>> n - long(float(n))
65535L
It's fairly straightforward to fix PyLong_AsDouble to return the closest
double to a given long integer n (using the round-half-to-even rule in
the case of a tie). The attached patch does this.
Having a correctly rounded float(n) can be useful for testing other
floating-point routines that are supposed to be correctly rounded.
|
| msg71997 (view) |
Author: David Jones (drj) |
Date: 2008-08-26 21:10 |
|
I agree, longs should be correctly rounded when coerced to floats.
There is an ugly (but amusing) workaround while people wait for this
patch: Go via a string:
int(float(repr(295147905179352891391)[:-1]))
Though I assume this relies on the platform's strtod working correctly.
Which it does for me.
|
| msg75510 (view) |
Author: STINNER Victor (haypo) |
Date: 2008-11-04 23:17 |
|
You may use "if (nbits == (size_t)-1 && PyErr_Occurred())" to check
_PyLong_NumBits() error (overflow). Well, "if (numbits > DBL_MAX_EXP)"
should already catch overflow, but I prefer explicit test to check the
error case.
Anyway, interresting patch! Python3 vanilla:
>>> n = 295147905179352891391; int(float(n)) - n
-65535
Python3 + your patch:
>>> int(float(n)) - n
1
|
| msg75568 (view) |
Author: Alexander Belopolsky (belopolsky) |
Date: 2008-11-06 17:30 |
|
Mark,
I noticed that you replaced a call to _PyLong_AsScaledDouble with your
round to nearest algorithm. I wonder if _PyLong_AsScaledDouble itself
would benefit from your change. Currently it is used in PyLong_AsDouble
and long_true_divide. I would think that long_true_divide would be more
accurate if longs were rounded to the nearest float.
I also wonder whether round to nearest float can be implemented without
floating point arithmetics. I would think round towards zero should be
a simple matter of extracting an appropriate number of bits from the
long and round to nearest would at most require a long addition.
I believe _PyLong_AsScaledDouble is written the way it is to support
non-IEEE floating formats, but I am not sure that your algorithm would
always return the nearest float on an arbitrary non-IEEE platform.
Maybe it would be worthwhile to provide a simple IEEE specific code with
well specified semantics for both PyLong_AsDouble and long_true_divide,
but fall back to the current code on non-IEEE platforms.
|
|
| Date |
User |
Action |
Args |
| 2008-11-06 17:30:34 | belopolsky | set | nosy:
+ belopolsky messages:
+ msg75568 |
| 2008-11-04 23:17:58 | haypo | set | messages:
+ msg75510 stage: patch review |
| 2008-11-04 23:07:09 | haypo | set | nosy:
+ haypo |
| 2008-08-26 21:10:32 | drj | set | nosy:
+ drj messages:
+ msg71997 |
| 2008-06-21 21:11:59 | marketdickinson | create | |
|