From 7321ec437b0aef968b83137d9c638551cabab706 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Thu, 26 Jul 2001 20:02:17 +0000 Subject: SF bug #444510: int() should guarantee truncation. It's guaranteed now, assuming the platform modf() works correctly. --- Doc/lib/libfuncs.tex | 4 +--- Lib/test/test_b1.py | 13 +++++++++++++ Objects/floatobject.c | 20 +++++++++++++------- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Doc/lib/libfuncs.tex b/Doc/lib/libfuncs.tex index e493375..12b7cf7 100644 --- a/Doc/lib/libfuncs.tex +++ b/Doc/lib/libfuncs.tex @@ -338,9 +338,7 @@ module from which it is called). \exception{TypeError} is raised. Otherwise, the argument may be a plain or long integer or a floating point number. Conversion of floating - point numbers to integers is defined by the C semantics; normally - the conversion truncates towards zero.\footnote{This is ugly --- the - language definition should require truncation towards zero.} + point numbers to integers truncates (towards zero). \end{funcdesc} \begin{funcdesc}{intern}{string} diff --git a/Lib/test/test_b1.py b/Lib/test/test_b1.py index e2cc49b..bddd157 100644 --- a/Lib/test/test_b1.py +++ b/Lib/test/test_b1.py @@ -366,6 +366,19 @@ except ValueError: pass else: raise TestFailed, "int(%s)" % `s[1:]` + " should raise ValueError" +try: + int(1e100) +except OverflowError: + pass +else: + raise TestFailed("int(1e100) expected OverflowError") +try: + int(-1e100) +except OverflowError: + pass +else: + raise TestFailed("int(-1e100) expected OverflowError") + # SF bug 434186: 0x80000000/2 != 0x80000000>>1. # Worked by accident in Windows release build, but failed in debug build. diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 2f17d02..d1ce092 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -606,13 +606,19 @@ static PyObject * float_int(PyObject *v) { double x = PyFloat_AsDouble(v); - if (x < 0 ? (x = ceil(x)) < (double)LONG_MIN - : (x = floor(x)) > (double)LONG_MAX) { - PyErr_SetString(PyExc_OverflowError, - "float too large to convert"); - return NULL; - } - return PyInt_FromLong((long)x); + double wholepart; /* integral portion of x, rounded toward 0 */ + long aslong; /* (long)wholepart */ + + (void)modf(x, &wholepart); + /* doubles may have more bits than longs, or vice versa; and casting + to long may yield gibberish in either case. What really matters + is whether converting back to double again reproduces what we + started with. */ + aslong = (long)wholepart; + if ((double)aslong == wholepart) + return PyInt_FromLong(aslong); + PyErr_SetString(PyExc_OverflowError, "float too large to convert"); + return NULL; } static PyObject * -- cgit v0.12