Finish the work on __round__ and __trunc__.

With Alex Martelli and Keir Mierle.
This commit is contained in:
Guido van Rossum 2007-08-23 22:07:24 +00:00
parent 0f3cff58b2
commit 2fa33db12b
4 changed files with 173 additions and 60 deletions

View file

@ -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 */