mirror of https://github.com/python/cpython
Continue rolling back pep-3141 changes that changed behavior from 2.5. This
round included: * Revert round to its 2.6 behavior (half away from 0). * Because round, floor, and ceil always return float again, it's no longer necessary to have them delegate to __xxx___, so I've ripped that out of their implementations and the Real ABC. This also helps in implementing types that work in both 2.6 and 3.0: you return int from the __xxx__ methods, and let it get enabled by the version upgrade. * Make pow(-1, .5) raise a ValueError again.
This commit is contained in:
parent
f7476c4d46
commit
9871d8fe22
|
@ -986,13 +986,10 @@ available. They are listed here in alphabetical order.
|
||||||
.. function:: round(x[, n])
|
.. function:: round(x[, n])
|
||||||
|
|
||||||
Return the floating point value *x* rounded to *n* digits after the decimal
|
Return the floating point value *x* rounded to *n* digits after the decimal
|
||||||
point. If *n* is omitted, it defaults to zero. Values are rounded to the
|
point. If *n* is omitted, it defaults to zero. The result is a floating point
|
||||||
closest multiple of 10 to the power minus *n*; if two multiples are equally
|
number. Values are rounded to the closest multiple of 10 to the power minus
|
||||||
close, rounding is done toward the even choice (so, for example, both
|
*n*; if two multiples are equally close, rounding is done away from 0 (so. for
|
||||||
``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is
|
example, ``round(0.5)`` is ``1.0`` and ``round(-0.5)`` is ``-1.0``).
|
||||||
``2``). Delegates to ``x.__round__(n)``.
|
|
||||||
|
|
||||||
.. versionchanged:: 2.6
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: set([iterable])
|
.. function:: set([iterable])
|
||||||
|
|
|
@ -26,9 +26,8 @@ Number-theoretic and representation functions:
|
||||||
|
|
||||||
.. function:: ceil(x)
|
.. function:: ceil(x)
|
||||||
|
|
||||||
Return the ceiling of *x* as a float, the smallest integer value greater than
|
Return the ceiling of *x* as a float, the smallest integer value greater than or
|
||||||
or equal to *x*. If *x* is not a float, delegates to ``x.__ceil__()``, which
|
equal to *x*.
|
||||||
should return an :class:`Integral` value.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: copysign(x, y)
|
.. function:: copysign(x, y)
|
||||||
|
@ -46,9 +45,8 @@ Number-theoretic and representation functions:
|
||||||
|
|
||||||
.. function:: floor(x)
|
.. function:: floor(x)
|
||||||
|
|
||||||
Return the floor of *x* as a float, the largest integer value less than or
|
Return the floor of *x* as a float, the largest integer value less than or equal
|
||||||
equal to *x*. If *x* is not a float, delegates to ``x.__floor__()``, which
|
to *x*.
|
||||||
should return an :class:`Integral` value.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: fmod(x, y)
|
.. function:: fmod(x, y)
|
||||||
|
|
|
@ -341,11 +341,11 @@ Notes:
|
||||||
pair: C; language
|
pair: C; language
|
||||||
|
|
||||||
Conversion from floating point to (long or plain) integer may round or
|
Conversion from floating point to (long or plain) integer may round or
|
||||||
truncate as in C.
|
truncate as in C; see functions :func:`math.floor` and :func:`math.ceil` for
|
||||||
|
well-defined conversions.
|
||||||
|
|
||||||
.. deprecated:: 2.6
|
.. deprecated:: 2.6
|
||||||
Instead, convert floats to long explicitly with :func:`trunc`,
|
Instead, convert floats to long explicitly with :func:`trunc`.
|
||||||
:func:`math.floor`, or :func:`math.ceil`.
|
|
||||||
|
|
||||||
(3)
|
(3)
|
||||||
See :ref:`built-in-funcs` for a full description.
|
See :ref:`built-in-funcs` for a full description.
|
||||||
|
@ -369,19 +369,19 @@ Notes:
|
||||||
All :class:`numbers.Real` types (:class:`int`, :class:`long`, and
|
All :class:`numbers.Real` types (:class:`int`, :class:`long`, and
|
||||||
:class:`float`) also include the following operations:
|
:class:`float`) also include the following operations:
|
||||||
|
|
||||||
+--------------------+--------------------------------+--------+
|
+--------------------+------------------------------------+--------+
|
||||||
| Operation | Result | Notes |
|
| Operation | Result | Notes |
|
||||||
+====================+================================+========+
|
+====================+====================================+========+
|
||||||
| ``trunc(x)`` | *x* truncated to Integral | |
|
| ``trunc(x)`` | *x* truncated to Integral | |
|
||||||
+--------------------+--------------------------------+--------+
|
+--------------------+------------------------------------+--------+
|
||||||
| ``round(x[, n])`` | *x* rounded to n digits, | |
|
| ``round(x[, n])`` | *x* rounded to n digits, | |
|
||||||
| | rounding half to even. If n is | |
|
| | rounding half to even. If n is | |
|
||||||
| | omitted, it defaults to 0. | |
|
| | omitted, it defaults to 0. | |
|
||||||
+--------------------+--------------------------------+--------+
|
+--------------------+------------------------------------+--------+
|
||||||
| ``math.floor(x)`` | the greatest Integral <= *x* | |
|
| ``math.floor(x)`` | the greatest integral float <= *x* | |
|
||||||
+--------------------+--------------------------------+--------+
|
+--------------------+------------------------------------+--------+
|
||||||
| ``math.ceil(x)`` | the least Integral >= *x* | |
|
| ``math.ceil(x)`` | the least integral float >= *x* | |
|
||||||
+--------------------+--------------------------------+--------+
|
+--------------------+------------------------------------+--------+
|
||||||
|
|
||||||
.. XXXJH exceptions: overflow (when? what operations?) zerodivision
|
.. XXXJH exceptions: overflow (when? what operations?) zerodivision
|
||||||
|
|
||||||
|
|
|
@ -801,8 +801,7 @@ were of integer types and the second argument was negative, an exception was
|
||||||
raised).
|
raised).
|
||||||
|
|
||||||
Raising ``0.0`` to a negative power results in a :exc:`ZeroDivisionError`.
|
Raising ``0.0`` to a negative power results in a :exc:`ZeroDivisionError`.
|
||||||
Raising a negative number to a fractional power results in a :class:`complex`
|
Raising a negative number to a fractional power results in a :exc:`ValueError`.
|
||||||
number. (Since Python 2.6. In earlier versions it raised a :exc:`ValueError`.)
|
|
||||||
|
|
||||||
|
|
||||||
.. _unary:
|
.. _unary:
|
||||||
|
|
|
@ -189,25 +189,6 @@ class Real(Complex):
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __floor__(self):
|
|
||||||
"""Finds the greatest Integral <= self."""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __ceil__(self):
|
|
||||||
"""Finds the least Integral >= self."""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __round__(self, ndigits=None):
|
|
||||||
"""Rounds self to ndigits decimal places, defaulting to 0.
|
|
||||||
|
|
||||||
If ndigits is omitted or None, returns an Integral, otherwise
|
|
||||||
returns a Real. Rounds half toward even.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def __divmod__(self, other):
|
def __divmod__(self, other):
|
||||||
"""divmod(self, other): The pair (self // other, self % other).
|
"""divmod(self, other): The pair (self // other, self % other).
|
||||||
|
|
||||||
|
|
|
@ -1456,13 +1456,12 @@ class BuiltinTest(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.assertAlmostEqual(pow(x, y, z), 24.0)
|
self.assertAlmostEqual(pow(x, y, z), 24.0)
|
||||||
|
|
||||||
self.assertAlmostEqual(pow(-1, 0.5), 1j)
|
|
||||||
self.assertAlmostEqual(pow(-1, 1./3), 0.5 + 0.8660254037844386j)
|
|
||||||
|
|
||||||
self.assertRaises(TypeError, pow, -1, -2, 3)
|
self.assertRaises(TypeError, pow, -1, -2, 3)
|
||||||
self.assertRaises(ValueError, pow, 1, 2, 0)
|
self.assertRaises(ValueError, pow, 1, 2, 0)
|
||||||
self.assertRaises(TypeError, pow, -1L, -2L, 3L)
|
self.assertRaises(TypeError, pow, -1L, -2L, 3L)
|
||||||
self.assertRaises(ValueError, pow, 1L, 2L, 0L)
|
self.assertRaises(ValueError, pow, 1L, 2L, 0L)
|
||||||
|
# Will return complex in 3.0:
|
||||||
|
self.assertRaises(ValueError, pow, -342.43, 0.234)
|
||||||
|
|
||||||
self.assertRaises(TypeError, pow)
|
self.assertRaises(TypeError, pow)
|
||||||
|
|
||||||
|
@ -1664,11 +1663,11 @@ class BuiltinTest(unittest.TestCase):
|
||||||
self.assertEqual(type(round(-8.0, 0)), float)
|
self.assertEqual(type(round(-8.0, 0)), float)
|
||||||
self.assertEqual(type(round(-8.0, 1)), float)
|
self.assertEqual(type(round(-8.0, 1)), float)
|
||||||
|
|
||||||
# Check even / odd rounding behaviour
|
# Check half rounding behaviour.
|
||||||
self.assertEqual(round(5.5), 6)
|
self.assertEqual(round(5.5), 6)
|
||||||
self.assertEqual(round(6.5), 6)
|
self.assertEqual(round(6.5), 7)
|
||||||
self.assertEqual(round(-5.5), -6)
|
self.assertEqual(round(-5.5), -6)
|
||||||
self.assertEqual(round(-6.5), -6)
|
self.assertEqual(round(-6.5), -7)
|
||||||
|
|
||||||
# Check behavior on ints
|
# Check behavior on ints
|
||||||
self.assertEqual(round(0), 0)
|
self.assertEqual(round(0), 0)
|
||||||
|
@ -1686,8 +1685,8 @@ class BuiltinTest(unittest.TestCase):
|
||||||
|
|
||||||
# test generic rounding delegation for reals
|
# test generic rounding delegation for reals
|
||||||
class TestRound(object):
|
class TestRound(object):
|
||||||
def __round__(self):
|
def __float__(self):
|
||||||
return 23
|
return 23.0
|
||||||
|
|
||||||
class TestNoRound(object):
|
class TestNoRound(object):
|
||||||
pass
|
pass
|
||||||
|
@ -1695,13 +1694,12 @@ class BuiltinTest(unittest.TestCase):
|
||||||
self.assertEqual(round(TestRound()), 23)
|
self.assertEqual(round(TestRound()), 23)
|
||||||
|
|
||||||
self.assertRaises(TypeError, round, 1, 2, 3)
|
self.assertRaises(TypeError, round, 1, 2, 3)
|
||||||
# XXX: This is not ideal, but see the comment in builtin_round().
|
self.assertRaises(TypeError, round, TestNoRound())
|
||||||
self.assertRaises(AttributeError, round, TestNoRound())
|
|
||||||
|
|
||||||
t = TestNoRound()
|
t = TestNoRound()
|
||||||
t.__round__ = lambda *args: args
|
t.__float__ = lambda *args: args
|
||||||
self.assertEquals((), round(t))
|
self.assertRaises(TypeError, round, t)
|
||||||
self.assertEquals((0,), round(t, 0))
|
self.assertRaises(TypeError, round, t, 0)
|
||||||
|
|
||||||
def test_setattr(self):
|
def test_setattr(self):
|
||||||
setattr(sys, 'spam', 1)
|
setattr(sys, 'spam', 1)
|
||||||
|
|
|
@ -385,9 +385,7 @@ class LongTest(unittest.TestCase):
|
||||||
"1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
|
"1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
|
||||||
"math.sin(huge)", "math.sin(mhuge)",
|
"math.sin(huge)", "math.sin(mhuge)",
|
||||||
"math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
|
"math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
|
||||||
# math.floor() of an int returns an int now
|
"math.floor(huge)", "math.floor(mhuge)"]:
|
||||||
##"math.floor(huge)", "math.floor(mhuge)",
|
|
||||||
]:
|
|
||||||
|
|
||||||
self.assertRaises(OverflowError, eval, test, namespace)
|
self.assertRaises(OverflowError, eval, test, namespace)
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,8 @@ class MathTests(unittest.TestCase):
|
||||||
self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
|
self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
|
||||||
|
|
||||||
class TestCeil(object):
|
class TestCeil(object):
|
||||||
def __ceil__(self):
|
def __float__(self):
|
||||||
return 42
|
return 41.3
|
||||||
class TestNoCeil(object):
|
class TestNoCeil(object):
|
||||||
pass
|
pass
|
||||||
self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
|
self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
|
||||||
|
@ -123,8 +123,8 @@ class MathTests(unittest.TestCase):
|
||||||
self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
|
self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
|
||||||
|
|
||||||
class TestFloor(object):
|
class TestFloor(object):
|
||||||
def __floor__(self):
|
def __float__(self):
|
||||||
return 42
|
return 42.3
|
||||||
class TestNoFloor(object):
|
class TestNoFloor(object):
|
||||||
pass
|
pass
|
||||||
self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42)
|
self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42)
|
||||||
|
|
|
@ -107,28 +107,9 @@ FUNC1(atan, atan,
|
||||||
FUNC2(atan2, atan2,
|
FUNC2(atan2, atan2,
|
||||||
"atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
|
"atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
|
||||||
"Unlike atan(y/x), the signs of both x and y are considered.")
|
"Unlike atan(y/x), the signs of both x and y are considered.")
|
||||||
|
FUNC1(ceil, ceil,
|
||||||
static PyObject * math_ceil(PyObject *self, PyObject *number) {
|
"ceil(x)\n\nReturn the ceiling of x as a float.\n"
|
||||||
static PyObject *ceil_str = NULL;
|
"This is the smallest integral value >= x.")
|
||||||
PyObject *method;
|
|
||||||
|
|
||||||
if (ceil_str == NULL) {
|
|
||||||
ceil_str = PyString_FromString("__ceil__");
|
|
||||||
if (ceil_str == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
method = _PyType_Lookup(Py_Type(number), ceil_str);
|
|
||||||
if (method == NULL)
|
|
||||||
return math_1(number, ceil);
|
|
||||||
else
|
|
||||||
return PyObject_CallFunction(method, "O", number);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(math_ceil_doc,
|
|
||||||
"ceil(x)\n\nReturn the ceiling of x as a float.\n"
|
|
||||||
"This is the smallest integral value >= x.");
|
|
||||||
|
|
||||||
FUNC1(cos, cos,
|
FUNC1(cos, cos,
|
||||||
"cos(x)\n\nReturn the cosine of x (measured in radians).")
|
"cos(x)\n\nReturn the cosine of x (measured in radians).")
|
||||||
FUNC1(cosh, cosh,
|
FUNC1(cosh, cosh,
|
||||||
|
@ -147,28 +128,9 @@ FUNC1(exp, exp,
|
||||||
"exp(x)\n\nReturn e raised to the power of x.")
|
"exp(x)\n\nReturn e raised to the power of x.")
|
||||||
FUNC1(fabs, fabs,
|
FUNC1(fabs, fabs,
|
||||||
"fabs(x)\n\nReturn the absolute value of the float x.")
|
"fabs(x)\n\nReturn the absolute value of the float x.")
|
||||||
|
FUNC1(floor, floor,
|
||||||
static PyObject * math_floor(PyObject *self, PyObject *number) {
|
"floor(x)\n\nReturn the floor of x as a float.\n"
|
||||||
static PyObject *floor_str = NULL;
|
"This is the largest integral value <= x.")
|
||||||
PyObject *method;
|
|
||||||
|
|
||||||
if (floor_str == NULL) {
|
|
||||||
floor_str = PyString_FromString("__floor__");
|
|
||||||
if (floor_str == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
method = _PyType_Lookup(Py_Type(number), floor_str);
|
|
||||||
if (method == NULL)
|
|
||||||
return math_1(number, floor);
|
|
||||||
else
|
|
||||||
return PyObject_CallFunction(method, "O", number);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(math_floor_doc,
|
|
||||||
"floor(x)\n\nReturn the floor of x as a float.\n"
|
|
||||||
"This is the largest integral value <= x.");
|
|
||||||
|
|
||||||
FUNC2(fmod, fmod,
|
FUNC2(fmod, fmod,
|
||||||
"fmod(x,y)\n\nReturn fmod(x, y), according to platform C."
|
"fmod(x,y)\n\nReturn fmod(x, y), according to platform C."
|
||||||
" x % y may differ.")
|
" x % y may differ.")
|
||||||
|
|
|
@ -986,10 +986,9 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
|
||||||
* bugs so we have to figure it out ourselves.
|
* bugs so we have to figure it out ourselves.
|
||||||
*/
|
*/
|
||||||
if (iw != floor(iw)) {
|
if (iw != floor(iw)) {
|
||||||
/* Negative numbers raised to fractional powers
|
PyErr_SetString(PyExc_ValueError, "negative number "
|
||||||
* become complex.
|
"cannot be raised to a fractional power");
|
||||||
*/
|
return NULL;
|
||||||
return PyComplex_Type.tp_as_number->nb_power(v, w, z);
|
|
||||||
}
|
}
|
||||||
/* iw is an exact integer, albeit perhaps a very large one.
|
/* iw is an exact integer, albeit perhaps a very large one.
|
||||||
* -1 raised to an exact integer should never be exceptional.
|
* -1 raised to an exact integer should never be exceptional.
|
||||||
|
@ -1098,54 +1097,6 @@ float_trunc(PyObject *v)
|
||||||
return PyLong_FromDouble(wholepart);
|
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);
|
|
||||||
#undef UNDEF_NDIGITS
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
float_float(PyObject *v)
|
float_float(PyObject *v)
|
||||||
{
|
{
|
||||||
|
@ -1344,9 +1295,6 @@ static PyMethodDef float_methods[] = {
|
||||||
"Returns self, the complex conjugate of any float."},
|
"Returns self, the complex conjugate of any float."},
|
||||||
{"__trunc__", (PyCFunction)float_trunc, METH_NOARGS,
|
{"__trunc__", (PyCFunction)float_trunc, METH_NOARGS,
|
||||||
"Returns the Integral closest to x between 0 and x."},
|
"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},
|
{"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS},
|
||||||
{"__getformat__", (PyCFunction)float_getformat,
|
{"__getformat__", (PyCFunction)float_getformat,
|
||||||
METH_O|METH_CLASS, float_getformat_doc},
|
METH_O|METH_CLASS, float_getformat_doc},
|
||||||
|
|
|
@ -1056,43 +1056,11 @@ int_getN(PyIntObject *v, void *context) {
|
||||||
return PyInt_FromLong((intptr_t)context);
|
return PyInt_FromLong((intptr_t)context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
int_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 int_float((PyIntObject *)self);
|
|
||||||
|
|
||||||
/* If called with two args, defer to float.__round__(). */
|
|
||||||
x = (double) PyInt_AS_LONG(self);
|
|
||||||
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 int_methods[] = {
|
static PyMethodDef int_methods[] = {
|
||||||
{"conjugate", (PyCFunction)int_int, METH_NOARGS,
|
{"conjugate", (PyCFunction)int_int, METH_NOARGS,
|
||||||
"Returns self, the complex conjugate of any int."},
|
"Returns self, the complex conjugate of any int."},
|
||||||
{"__trunc__", (PyCFunction)int_int, METH_NOARGS,
|
{"__trunc__", (PyCFunction)int_int, METH_NOARGS,
|
||||||
"Truncating an Integral returns itself."},
|
"Truncating an Integral returns itself."},
|
||||||
{"__floor__", (PyCFunction)int_float, METH_NOARGS,
|
|
||||||
"Flooring an Integral returns itself."},
|
|
||||||
{"__ceil__", (PyCFunction)int_float, METH_NOARGS,
|
|
||||||
"Ceiling of an Integral returns itself."},
|
|
||||||
{"__round__", (PyCFunction)int_round, METH_VARARGS,
|
|
||||||
"Rounding an Integral returns itself.\n"
|
|
||||||
"Rounding with an ndigits arguments defers to float.__round__."},
|
|
||||||
{"__getnewargs__", (PyCFunction)int_getnewargs, METH_NOARGS},
|
{"__getnewargs__", (PyCFunction)int_getnewargs, METH_NOARGS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
|
@ -3370,45 +3370,11 @@ long_getN(PyLongObject *v, void *context) {
|
||||||
return PyLong_FromLong((intptr_t)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_float(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[] = {
|
static PyMethodDef long_methods[] = {
|
||||||
{"conjugate", (PyCFunction)long_long, METH_NOARGS,
|
{"conjugate", (PyCFunction)long_long, METH_NOARGS,
|
||||||
"Returns self, the complex conjugate of any long."},
|
"Returns self, the complex conjugate of any long."},
|
||||||
{"__trunc__", (PyCFunction)long_long, METH_NOARGS,
|
{"__trunc__", (PyCFunction)long_long, METH_NOARGS,
|
||||||
"Truncating an Integral returns itself."},
|
"Truncating an Integral returns itself."},
|
||||||
{"__floor__", (PyCFunction)long_float, METH_NOARGS,
|
|
||||||
"Flooring an Integral returns itself."},
|
|
||||||
{"__ceil__", (PyCFunction)long_float, 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},
|
{"__getnewargs__", (PyCFunction)long_getnewargs, METH_NOARGS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
|
@ -1926,31 +1926,39 @@ For most object types, eval(repr(object)) == object.");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
builtin_round(PyObject *self, PyObject *args, PyObject *kwds)
|
builtin_round(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */
|
double number;
|
||||||
int ndigits = UNDEF_NDIGITS;
|
double f;
|
||||||
|
int ndigits = 0;
|
||||||
|
int i;
|
||||||
static char *kwlist[] = {"number", "ndigits", 0};
|
static char *kwlist[] = {"number", "ndigits", 0};
|
||||||
PyObject *number;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:round",
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|i:round",
|
||||||
kwlist, &number, &ndigits))
|
kwlist, &number, &ndigits))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
f = 1.0;
|
||||||
// The py3k branch gets better errors for this by using
|
i = abs(ndigits);
|
||||||
// _PyType_Lookup(), but since float's mro isn't set in py2.6,
|
while (--i >= 0)
|
||||||
// we just use PyObject_CallMethod here.
|
f = f*10.0;
|
||||||
if (ndigits == UNDEF_NDIGITS)
|
if (ndigits < 0)
|
||||||
return PyObject_CallMethod(number, "__round__", "");
|
number /= f;
|
||||||
else
|
else
|
||||||
return PyObject_CallMethod(number, "__round__", "i", ndigits);
|
number *= f;
|
||||||
#undef UNDEF_NDIGITS
|
if (number >= 0.0)
|
||||||
|
number = floor(number + 0.5);
|
||||||
|
else
|
||||||
|
number = ceil(number - 0.5);
|
||||||
|
if (ndigits < 0)
|
||||||
|
number *= f;
|
||||||
|
else
|
||||||
|
number /= f;
|
||||||
|
return PyFloat_FromDouble(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(round_doc,
|
PyDoc_STRVAR(round_doc,
|
||||||
"round(number[, ndigits]) -> floating point number\n\
|
"round(number[, ndigits]) -> floating point number\n\
|
||||||
\n\
|
\n\
|
||||||
Round a number to a given precision in decimal digits (default 0 digits).\n\
|
Round a number to a given precision in decimal digits (default 0 digits).\n\
|
||||||
This returns an int when called with one argument, otherwise a float.\n\
|
This always returns a floating point number. Precision may be negative.");
|
||||||
Precision may be negative.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds)
|
builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
|
Loading…
Reference in New Issue