From f263724ea0e97de8644a651f4d78926fa995e209 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 9 Nov 2009 17:45:40 +0000 Subject: [PATCH] Issue #7070: Fix problem with builtin round function for large odd integer arguments. Also fixes the sign of round(-0.0). --- Lib/test/test_builtin.py | 9 +++++++++ Misc/NEWS | 2 ++ Python/bltinmodule.c | 14 +++++++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index d8e604158c7..04c22167654 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1,5 +1,6 @@ # Python test set -- built-in functions +import platform import test.test_support, unittest from test.test_support import fcmp, have_unicode, TESTFN, unlink, \ run_unittest, run_with_locale @@ -1259,6 +1260,14 @@ class BuiltinTest(unittest.TestCase): self.assertRaises(TypeError, round, t) self.assertRaises(TypeError, round, t, 0) + def test_round_large(self): + # Issue #1869: integral floats should remain unchanged + self.assertEqual(round(5e15-1), 5e15-1) + self.assertEqual(round(5e15), 5e15) + self.assertEqual(round(5e15+1), 5e15+1) + self.assertEqual(round(5e15+2), 5e15+2) + self.assertEqual(round(5e15+3), 5e15+3) + def test_setattr(self): setattr(sys, 'spam', 1) self.assertEqual(sys.spam, 1) diff --git a/Misc/NEWS b/Misc/NEWS index 6d421872649..ae1be757293 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,8 @@ What's New in Python 2.6.5 Core and Builtins ----------------- +- Issue #7070: Fix round bug for large odd integer arguments. + - Issue #7078: Set struct.__doc__ from _struct.__doc__. - Issue #1722344: threading._shutdown() is now called in Py_Finalize(), which diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 015e16bbb87..87da3c9fff1 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2120,7 +2120,7 @@ For most object types, eval(repr(object)) == object."); static PyObject * builtin_round(PyObject *self, PyObject *args, PyObject *kwds) { - double number; + double number, abs_number, abs_result; double f; int ndigits = 0; int i; @@ -2137,10 +2137,14 @@ builtin_round(PyObject *self, PyObject *args, PyObject *kwds) number /= f; else number *= f; - if (number >= 0.0) - number = floor(number + 0.5); - else - number = ceil(number - 0.5); + + /* round `number` to nearest integer, rounding halves away from zero */ + abs_number = fabs(number); + abs_result = floor(abs_number); + if (abs_number - abs_result >= 0.5) + abs_result += 1.0; + number = copysign(abs_result, number); + if (ndigits < 0) number *= f; else