mirror of
https://github.com/python/cpython.git
synced 2025-08-03 08:34:29 +00:00
Finish the work on __round__ and __trunc__.
With Alex Martelli and Keir Mierle.
This commit is contained in:
parent
0f3cff58b2
commit
2fa33db12b
4 changed files with 173 additions and 60 deletions
|
@ -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 */
|
||||
|
@ -775,6 +768,55 @@ float_int(PyObject *v)
|
|||
return PyLong_FromDouble(wholepart);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue