mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	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
					
				
					 13 changed files with 75 additions and 252 deletions
				
			
		|  | @ -986,13 +986,10 @@ available.  They are listed here in alphabetical order. | |||
| .. function:: round(x[, n]) | ||||
| 
 | ||||
|    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 | ||||
|    closest multiple of 10 to the power minus *n*; if two multiples are equally | ||||
|    close, rounding is done toward the even choice (so, for example, both | ||||
|    ``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is | ||||
|    ``2``). Delegates to ``x.__round__(n)``. | ||||
| 
 | ||||
|    .. versionchanged:: 2.6 | ||||
|    point.  If *n* is omitted, it defaults to zero. The result is a floating point | ||||
|    number.  Values are rounded to the closest multiple of 10 to the power minus | ||||
|    *n*; if two multiples are equally close, rounding is done away from 0 (so. for | ||||
|    example, ``round(0.5)`` is ``1.0`` and ``round(-0.5)`` is ``-1.0``). | ||||
| 
 | ||||
| 
 | ||||
| .. function:: set([iterable]) | ||||
|  |  | |||
|  | @ -26,9 +26,8 @@ Number-theoretic and representation functions: | |||
| 
 | ||||
| .. function:: ceil(x) | ||||
| 
 | ||||
|    Return the ceiling of *x* as a float, the smallest integer value greater than | ||||
|    or equal to *x*. If *x* is not a float, delegates to ``x.__ceil__()``, which | ||||
|    should return an :class:`Integral` value. | ||||
|    Return the ceiling of *x* as a float, the smallest integer value greater than or | ||||
|    equal to *x*. | ||||
| 
 | ||||
| 
 | ||||
| .. function:: copysign(x, y) | ||||
|  | @ -46,9 +45,8 @@ Number-theoretic and representation functions: | |||
| 
 | ||||
| .. function:: floor(x) | ||||
| 
 | ||||
|    Return the floor of *x* as a float, the largest integer value less than or | ||||
|    equal to *x*. If *x* is not a float, delegates to ``x.__floor__()``, which | ||||
|    should return an :class:`Integral` value. | ||||
|    Return the floor of *x* as a float, the largest integer value less than or equal | ||||
|    to *x*. | ||||
| 
 | ||||
| 
 | ||||
| .. function:: fmod(x, y) | ||||
|  |  | |||
|  | @ -341,11 +341,11 @@ Notes: | |||
|       pair: C; language | ||||
| 
 | ||||
|    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 | ||||
|       Instead, convert floats to long explicitly with :func:`trunc`, | ||||
|       :func:`math.floor`, or :func:`math.ceil`. | ||||
|       Instead, convert floats to long explicitly with :func:`trunc`. | ||||
| 
 | ||||
| (3) | ||||
|    See :ref:`built-in-funcs` for a full description. | ||||
|  | @ -369,19 +369,19 @@ Notes: | |||
| All :class:`numbers.Real` types (:class:`int`, :class:`long`, and | ||||
| :class:`float`) also include the following operations: | ||||
| 
 | ||||
| +--------------------+--------------------------------+--------+ | ||||
| | Operation          | Result                         | Notes  | | ||||
| +====================+================================+========+ | ||||
| | ``trunc(x)``       | *x* truncated to Integral      |        | | ||||
| +--------------------+--------------------------------+--------+ | ||||
| | ``round(x[, n])``  | *x* rounded to n digits,       |        | | ||||
| |                    | rounding half to even. If n is |        | | ||||
| |                    | omitted, it defaults to 0.     |        | | ||||
| +--------------------+--------------------------------+--------+ | ||||
| | ``math.floor(x)``  | the greatest Integral <= *x*   |        | | ||||
| +--------------------+--------------------------------+--------+ | ||||
| | ``math.ceil(x)``   | the least Integral >= *x*      |        | | ||||
| +--------------------+--------------------------------+--------+ | ||||
| +--------------------+------------------------------------+--------+ | ||||
| | Operation          | Result                             | Notes  | | ||||
| +====================+====================================+========+ | ||||
| | ``trunc(x)``       | *x* truncated to Integral          |        | | ||||
| +--------------------+------------------------------------+--------+ | ||||
| | ``round(x[, n])``  | *x* rounded to n digits,           |        | | ||||
| |                    | rounding half to even. If n is     |        | | ||||
| |                    | omitted, it defaults to 0.         |        | | ||||
| +--------------------+------------------------------------+--------+ | ||||
| | ``math.floor(x)``  | the greatest integral float <= *x* |        | | ||||
| +--------------------+------------------------------------+--------+ | ||||
| | ``math.ceil(x)``   | the least integral float >= *x*    |        | | ||||
| +--------------------+------------------------------------+--------+ | ||||
| 
 | ||||
| .. 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). | ||||
| 
 | ||||
| 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` | ||||
| number. (Since Python 2.6. In earlier versions it raised a :exc:`ValueError`.) | ||||
| Raising a negative number to a fractional power results in a :exc:`ValueError`. | ||||
| 
 | ||||
| 
 | ||||
| .. _unary: | ||||
|  |  | |||
|  | @ -189,25 +189,6 @@ def __trunc__(self): | |||
|         """ | ||||
|         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): | ||||
|         """divmod(self, other): The pair (self // other, self % other). | ||||
| 
 | ||||
|  |  | |||
|  | @ -1456,13 +1456,12 @@ def test_pow(self): | |||
|                     else: | ||||
|                         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(ValueError, pow, 1, 2, 0) | ||||
|         self.assertRaises(TypeError, pow, -1L, -2L, 3L) | ||||
|         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) | ||||
| 
 | ||||
|  | @ -1664,11 +1663,11 @@ def test_round(self): | |||
|         self.assertEqual(type(round(-8.0, 0)), 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(6.5), 6) | ||||
|         self.assertEqual(round(6.5), 7) | ||||
|         self.assertEqual(round(-5.5), -6) | ||||
|         self.assertEqual(round(-6.5), -6) | ||||
|         self.assertEqual(round(-6.5), -7) | ||||
| 
 | ||||
|         # Check behavior on ints | ||||
|         self.assertEqual(round(0), 0) | ||||
|  | @ -1686,8 +1685,8 @@ def test_round(self): | |||
| 
 | ||||
|         # test generic rounding delegation for reals | ||||
|         class TestRound(object): | ||||
|             def __round__(self): | ||||
|                 return 23 | ||||
|             def __float__(self): | ||||
|                 return 23.0 | ||||
| 
 | ||||
|         class TestNoRound(object): | ||||
|             pass | ||||
|  | @ -1695,13 +1694,12 @@ class TestNoRound(object): | |||
|         self.assertEqual(round(TestRound()), 23) | ||||
| 
 | ||||
|         self.assertRaises(TypeError, round, 1, 2, 3) | ||||
|         # XXX: This is not ideal, but see the comment in builtin_round(). | ||||
|         self.assertRaises(AttributeError, round, TestNoRound()) | ||||
|         self.assertRaises(TypeError, round, TestNoRound()) | ||||
| 
 | ||||
|         t = TestNoRound() | ||||
|         t.__round__ = lambda *args: args | ||||
|         self.assertEquals((), round(t)) | ||||
|         self.assertEquals((0,), round(t, 0)) | ||||
|         t.__float__ = lambda *args: args | ||||
|         self.assertRaises(TypeError, round, t) | ||||
|         self.assertRaises(TypeError, round, t, 0) | ||||
| 
 | ||||
|     def test_setattr(self): | ||||
|         setattr(sys, 'spam', 1) | ||||
|  |  | |||
|  | @ -385,9 +385,7 @@ def test_float_overflow(self): | |||
|                      "1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.", | ||||
|                      "math.sin(huge)", "math.sin(mhuge)", | ||||
|                      "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) | ||||
| 
 | ||||
|  |  | |||
|  | @ -63,8 +63,8 @@ def testCeil(self): | |||
|         self.ftest('ceil(-1.5)', math.ceil(-1.5), -1) | ||||
| 
 | ||||
|         class TestCeil(object): | ||||
|             def __ceil__(self): | ||||
|                 return 42 | ||||
|             def __float__(self): | ||||
|                 return 41.3 | ||||
|         class TestNoCeil(object): | ||||
|             pass | ||||
|         self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42) | ||||
|  | @ -123,8 +123,8 @@ def testFloor(self): | |||
|         self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167) | ||||
| 
 | ||||
|         class TestFloor(object): | ||||
|             def __floor__(self): | ||||
|                 return 42 | ||||
|             def __float__(self): | ||||
|                 return 42.3 | ||||
|         class TestNoFloor(object): | ||||
|             pass | ||||
|         self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42) | ||||
|  |  | |||
|  | @ -107,28 +107,9 @@ FUNC1(atan, atan, | |||
| FUNC2(atan2, atan2, | ||||
|       "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.") | ||||
| 
 | ||||
| static PyObject * math_ceil(PyObject *self, PyObject *number) { | ||||
| 	static PyObject *ceil_str = NULL; | ||||
| 	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(ceil, ceil, | ||||
|       "ceil(x)\n\nReturn the ceiling of x as a float.\n" | ||||
|       "This is the smallest integral value >= x.") | ||||
| FUNC1(cos, cos, | ||||
|       "cos(x)\n\nReturn the cosine of x (measured in radians).") | ||||
| FUNC1(cosh, cosh, | ||||
|  | @ -147,28 +128,9 @@ FUNC1(exp, exp, | |||
|       "exp(x)\n\nReturn e raised to the power of x.") | ||||
| FUNC1(fabs, fabs, | ||||
|       "fabs(x)\n\nReturn the absolute value of the float x.") | ||||
| 
 | ||||
| static PyObject * math_floor(PyObject *self, PyObject *number) { | ||||
| 	static PyObject *floor_str = NULL; | ||||
| 	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."); | ||||
| 
 | ||||
| FUNC1(floor, floor, | ||||
|       "floor(x)\n\nReturn the floor of x as a float.\n" | ||||
|       "This is the largest integral value <= x.") | ||||
| FUNC2(fmod, fmod, | ||||
|       "fmod(x,y)\n\nReturn fmod(x, y), according to platform C." | ||||
|       "  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. | ||||
| 		 */ | ||||
| 		if (iw != floor(iw)) { | ||||
| 			/* Negative numbers raised to fractional powers
 | ||||
| 			 * become complex. | ||||
| 			 */ | ||||
| 			return PyComplex_Type.tp_as_number->nb_power(v, w, z); | ||||
| 			PyErr_SetString(PyExc_ValueError, "negative number " | ||||
| 				"cannot be raised to a fractional power"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		/* iw is an exact integer, albeit perhaps a very large one.
 | ||||
| 		 * -1 raised to an exact integer should never be exceptional. | ||||
|  | @ -1098,54 +1097,6 @@ float_trunc(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); | ||||
| #undef UNDEF_NDIGITS | ||||
| } | ||||
| 
 | ||||
| static PyObject * | ||||
| float_float(PyObject *v) | ||||
| { | ||||
|  | @ -1344,9 +1295,6 @@ static PyMethodDef float_methods[] = { | |||
| 	 "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}, | ||||
|  |  | |||
|  | @ -1056,43 +1056,11 @@ int_getN(PyIntObject *v, void *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[] = { | ||||
| 	{"conjugate",	(PyCFunction)int_int,	METH_NOARGS, | ||||
| 	 "Returns self, the complex conjugate of any int."}, | ||||
| 	{"__trunc__",	(PyCFunction)int_int,	METH_NOARGS, | ||||
|          "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}, | ||||
| 	{NULL,		NULL}		/* sentinel */ | ||||
| }; | ||||
|  |  | |||
|  | @ -3370,45 +3370,11 @@ 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_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[] = { | ||||
| 	{"conjugate",	(PyCFunction)long_long,	METH_NOARGS, | ||||
| 	 "Returns self, the complex conjugate of any long."}, | ||||
| 	{"__trunc__",	(PyCFunction)long_long,	METH_NOARGS, | ||||
|          "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}, | ||||
| 	{NULL,		NULL}		/* sentinel */ | ||||
| }; | ||||
|  |  | |||
|  | @ -1926,31 +1926,39 @@ For most object types, eval(repr(object)) == object."); | |||
| static PyObject * | ||||
| builtin_round(PyObject *self, PyObject *args, PyObject *kwds) | ||||
| { | ||||
| #define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */ | ||||
| 	int ndigits = UNDEF_NDIGITS; | ||||
| 	double number; | ||||
| 	double f; | ||||
| 	int ndigits = 0; | ||||
| 	int i; | ||||
| 	static char *kwlist[] = {"number", "ndigits", 0}; | ||||
| 	PyObject *number; | ||||
| 
 | ||||
| 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:round", | ||||
|                 kwlist, &number, &ndigits)) | ||||
|                 return NULL; | ||||
| 
 | ||||
|         // The py3k branch gets better errors for this by using
 | ||||
|         // _PyType_Lookup(), but since float's mro isn't set in py2.6,
 | ||||
|         // we just use PyObject_CallMethod here.
 | ||||
|         if (ndigits == UNDEF_NDIGITS) | ||||
|                 return PyObject_CallMethod(number, "__round__", ""); | ||||
|         else | ||||
|                 return PyObject_CallMethod(number, "__round__", "i", ndigits); | ||||
| #undef UNDEF_NDIGITS | ||||
| 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|i:round", | ||||
| 		kwlist, &number, &ndigits)) | ||||
| 		return NULL; | ||||
| 	f = 1.0; | ||||
| 	i = abs(ndigits); | ||||
| 	while  (--i >= 0) | ||||
| 		f = f*10.0; | ||||
| 	if (ndigits < 0) | ||||
| 		number /= f; | ||||
| 	else | ||||
| 		number *= f; | ||||
| 	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, | ||||
| "round(number[, ndigits]) -> floating point number\n\
 | ||||
| \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\ | ||||
| Precision may be negative."); | ||||
| This always returns a floating point number.  Precision may be negative."); | ||||
| 
 | ||||
| static PyObject * | ||||
| builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeffrey Yasskin
						Jeffrey Yasskin