]> granicus.if.org Git - python/commitdiff
SF bug #444510: int() should guarantee truncation.
authorTim Peters <tim.peters@gmail.com>
Thu, 26 Jul 2001 20:02:17 +0000 (20:02 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 26 Jul 2001 20:02:17 +0000 (20:02 +0000)
It's guaranteed now, assuming the platform modf() works correctly.

Doc/lib/libfuncs.tex
Lib/test/test_b1.py
Objects/floatobject.c

index e493375186be901b8cee57346b8c0a250f5aef45..12b7cf7793623fed72decebe12ca7c01f8f56c85 100644 (file)
@@ -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}
index e2cc49b16ab00d29c3d79c88dffaa102954cf678..bddd157ad5477189caa37f2d175de98af12bb5fe 100644 (file)
@@ -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.
index 2f17d02837e559685c0272946301e8a2d9a3b5d5..d1ce09271244fe83e6a1b420470e96c35331a8d6 100644 (file)
@@ -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 *