diff Python/bltinmodule.c @ 44488:94eeaeeb3ce9 legacy-trunk

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.
author Jeffrey Yasskin <jyasskin@gmail.com>
date Sat, 05 Jan 2008 08:47:13 +0000
parents 4f9723d9ca32
children 9caf8a7b11a6
line wrap: on
line diff
--- a/Python/bltinmodule.c	Sat Jan 05 04:38:38 2008 +0000
+++ b/Python/bltinmodule.c	Sat Jan 05 08:47:13 2008 +0000
@@ -1926,31 +1926,39 @@
 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)