diff options
author | Guido van Rossum <guido@python.org> | 2007-08-23 22:07:24 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2007-08-23 22:07:24 (GMT) |
commit | 2fa33db12b8cb6ec1dd1b87df6911e311d98457b (patch) | |
tree | cdc7d475186715895ae3457e91bf0d3c3b7c5e03 /Objects | |
parent | 0f3cff58b284e0098eab71b80d0001e173e6981a (diff) | |
download | cpython-2fa33db12b8cb6ec1dd1b87df6911e311d98457b.zip cpython-2fa33db12b8cb6ec1dd1b87df6911e311d98457b.tar.gz cpython-2fa33db12b8cb6ec1dd1b87df6911e311d98457b.tar.bz2 |
Finish the work on __round__ and __trunc__.
With Alex Martelli and Keir Mierle.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/floatobject.c | 67 | ||||
-rw-r--r-- | Objects/longobject.c | 36 |
2 files changed, 93 insertions, 10 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 908258c..09efa12 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -743,14 +743,7 @@ float_bool(PyFloatObject *v) } static PyObject * -float_long(PyObject *v) -{ - double x = PyFloat_AsDouble(v); - return PyLong_FromDouble(x); -} - -static PyObject * -float_int(PyObject *v) +float_trunc(PyObject *v) { double x = PyFloat_AsDouble(v); double wholepart; /* integral portion of x, rounded toward 0 */ @@ -776,6 +769,55 @@ float_int(PyObject *v) } static PyObject * +float_round(PyObject *v, PyObject *args) +{ +#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */ + double x; + double f; + double flr, cil; + double rounded; + int i; + int ndigits = UNDEF_NDIGITS; + + if (!PyArg_ParseTuple(args, "|i", &ndigits)) + return NULL; + + x = PyFloat_AsDouble(v); + + if (ndigits != UNDEF_NDIGITS) { + f = 1.0; + i = abs(ndigits); + while (--i >= 0) + f = f*10.0; + if (ndigits < 0) + x /= f; + else + x *= f; + } + + flr = floor(x); + cil = ceil(x); + + if (x-flr > 0.5) + rounded = cil; + else if (x-flr == 0.5) + rounded = fmod(flr, 2) == 0 ? flr : cil; + else + rounded = flr; + + if (ndigits != UNDEF_NDIGITS) { + if (ndigits < 0) + rounded *= f; + else + rounded /= f; + return PyFloat_FromDouble(rounded); + } + + return PyLong_FromDouble(rounded); +#undef UNDEF_NDIGITS +} + +static PyObject * float_float(PyObject *v) { if (PyFloat_CheckExact(v)) @@ -976,6 +1018,11 @@ float_getzero(PyObject *v, void *closure) static PyMethodDef float_methods[] = { {"conjugate", (PyCFunction)float_float, METH_NOARGS, "Returns self, the complex conjugate of any float."}, + {"__trunc__", (PyCFunction)float_trunc, METH_NOARGS, + "Returns the Integral closest to x between 0 and x."}, + {"__round__", (PyCFunction)float_round, METH_VARARGS, + "Returns the Integral closest to x, rounding half toward even.\n" + "When an argument is passed, works like built-in round(x, ndigits)."}, {"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS}, {"__getformat__", (PyCFunction)float_getformat, METH_O|METH_CLASS, float_getformat_doc}, @@ -1020,8 +1067,8 @@ static PyNumberMethods float_as_number = { 0, /*nb_xor*/ 0, /*nb_or*/ (coercion)0, /*nb_coerce*/ - float_int, /*nb_int*/ - float_long, /*nb_long*/ + float_trunc, /*nb_int*/ + float_trunc, /*nb_long*/ float_float, /*nb_float*/ 0, /* nb_oct */ 0, /* nb_hex */ diff --git a/Objects/longobject.c b/Objects/longobject.c index 518e607..ddf359d 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -3592,9 +3592,45 @@ long_getN(PyLongObject *v, void *context) { return PyLong_FromLong((intptr_t)context); } +static PyObject * +long_round(PyObject *self, PyObject *args) +{ +#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */ + int ndigits = UNDEF_NDIGITS; + double x; + PyObject *res; + + if (!PyArg_ParseTuple(args, "|i", &ndigits)) + return NULL; + + if (ndigits == UNDEF_NDIGITS) + return long_long(self); + + /* If called with two args, defer to float.__round__(). */ + x = PyLong_AsDouble(self); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + self = PyFloat_FromDouble(x); + if (self == NULL) + return NULL; + res = PyObject_CallMethod(self, "__round__", "i", ndigits); + Py_DECREF(self); + return res; +#undef UNDEF_NDIGITS +} + static PyMethodDef long_methods[] = { {"conjugate", (PyCFunction)long_long, METH_NOARGS, "Returns self, the complex conjugate of any int."}, + {"__trunc__", (PyCFunction)long_long, METH_NOARGS, + "Truncating an Integral returns itself."}, + {"__floor__", (PyCFunction)long_long, METH_NOARGS, + "Flooring an Integral returns itself."}, + {"__ceil__", (PyCFunction)long_long, METH_NOARGS, + "Ceiling of an Integral returns itself."}, + {"__round__", (PyCFunction)long_round, METH_VARARGS, + "Rounding an Integral returns itself.\n" + "Rounding with an ndigits arguments defers to float.__round__."}, {"__getnewargs__", (PyCFunction)long_getnewargs, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; |