Skip to content

Commit efe5c73

Browse files
author
jeffrey.yasskin
committed
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. git-svn-id: http://svn.python.org/projects/python/trunk@59731 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 5ee3afd commit efe5c73

13 files changed

Lines changed: 75 additions & 252 deletions

File tree

Doc/library/functions.rst

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -986,13 +986,10 @@ available. They are listed here in alphabetical order.
986986
.. function:: round(x[, n])
987987

988988
Return the floating point value *x* rounded to *n* digits after the decimal
989-
point. If *n* is omitted, it defaults to zero. Values are rounded to the
990-
closest multiple of 10 to the power minus *n*; if two multiples are equally
991-
close, rounding is done toward the even choice (so, for example, both
992-
``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is
993-
``2``). Delegates to ``x.__round__(n)``.
994-
995-
.. versionchanged:: 2.6
989+
point. If *n* is omitted, it defaults to zero. The result is a floating point
990+
number. Values are rounded to the closest multiple of 10 to the power minus
991+
*n*; if two multiples are equally close, rounding is done away from 0 (so. for
992+
example, ``round(0.5)`` is ``1.0`` and ``round(-0.5)`` is ``-1.0``).
996993

997994

998995
.. function:: set([iterable])

Doc/library/math.rst

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ Number-theoretic and representation functions:
2626

2727
.. function:: ceil(x)
2828

29-
Return the ceiling of *x* as a float, the smallest integer value greater than
30-
or equal to *x*. If *x* is not a float, delegates to ``x.__ceil__()``, which
31-
should return an :class:`Integral` value.
29+
Return the ceiling of *x* as a float, the smallest integer value greater than or
30+
equal to *x*.
3231

3332

3433
.. function:: copysign(x, y)
@@ -46,9 +45,8 @@ Number-theoretic and representation functions:
4645

4746
.. function:: floor(x)
4847

49-
Return the floor of *x* as a float, the largest integer value less than or
50-
equal to *x*. If *x* is not a float, delegates to ``x.__floor__()``, which
51-
should return an :class:`Integral` value.
48+
Return the floor of *x* as a float, the largest integer value less than or equal
49+
to *x*.
5250

5351

5452
.. function:: fmod(x, y)

Doc/library/stdtypes.rst

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,11 @@ Notes:
341341
pair: C; language
342342

343343
Conversion from floating point to (long or plain) integer may round or
344-
truncate as in C.
344+
truncate as in C; see functions :func:`math.floor` and :func:`math.ceil` for
345+
well-defined conversions.
345346

346347
.. deprecated:: 2.6
347-
Instead, convert floats to long explicitly with :func:`trunc`,
348-
:func:`math.floor`, or :func:`math.ceil`.
348+
Instead, convert floats to long explicitly with :func:`trunc`.
349349

350350
(3)
351351
See :ref:`built-in-funcs` for a full description.
@@ -369,19 +369,19 @@ Notes:
369369
All :class:`numbers.Real` types (:class:`int`, :class:`long`, and
370370
:class:`float`) also include the following operations:
371371

372-
+--------------------+--------------------------------+--------+
373-
| Operation | Result | Notes |
374-
+====================+================================+========+
375-
| ``trunc(x)`` | *x* truncated to Integral | |
376-
+--------------------+--------------------------------+--------+
377-
| ``round(x[, n])`` | *x* rounded to n digits, | |
378-
| | rounding half to even. If n is | |
379-
| | omitted, it defaults to 0. | |
380-
+--------------------+--------------------------------+--------+
381-
| ``math.floor(x)`` | the greatest Integral <= *x* | |
382-
+--------------------+--------------------------------+--------+
383-
| ``math.ceil(x)`` | the least Integral >= *x* | |
384-
+--------------------+--------------------------------+--------+
372+
+--------------------+------------------------------------+--------+
373+
| Operation | Result | Notes |
374+
+====================+====================================+========+
375+
| ``trunc(x)`` | *x* truncated to Integral | |
376+
+--------------------+------------------------------------+--------+
377+
| ``round(x[, n])`` | *x* rounded to n digits, | |
378+
| | rounding half to even. If n is | |
379+
| | omitted, it defaults to 0. | |
380+
+--------------------+------------------------------------+--------+
381+
| ``math.floor(x)`` | the greatest integral float <= *x* | |
382+
+--------------------+------------------------------------+--------+
383+
| ``math.ceil(x)`` | the least integral float >= *x* | |
384+
+--------------------+------------------------------------+--------+
385385

386386
.. XXXJH exceptions: overflow (when? what operations?) zerodivision
387387

Doc/reference/expressions.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,8 +801,7 @@ were of integer types and the second argument was negative, an exception was
801801
raised).
802802

803803
Raising ``0.0`` to a negative power results in a :exc:`ZeroDivisionError`.
804-
Raising a negative number to a fractional power results in a :class:`complex`
805-
number. (Since Python 2.6. In earlier versions it raised a :exc:`ValueError`.)
804+
Raising a negative number to a fractional power results in a :exc:`ValueError`.
806805

807806

808807
.. _unary:

Lib/numbers.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -189,25 +189,6 @@ def __trunc__(self):
189189
"""
190190
raise NotImplementedError
191191

192-
@abstractmethod
193-
def __floor__(self):
194-
"""Finds the greatest Integral <= self."""
195-
raise NotImplementedError
196-
197-
@abstractmethod
198-
def __ceil__(self):
199-
"""Finds the least Integral >= self."""
200-
raise NotImplementedError
201-
202-
@abstractmethod
203-
def __round__(self, ndigits=None):
204-
"""Rounds self to ndigits decimal places, defaulting to 0.
205-
206-
If ndigits is omitted or None, returns an Integral, otherwise
207-
returns a Real. Rounds half toward even.
208-
"""
209-
raise NotImplementedError
210-
211192
def __divmod__(self, other):
212193
"""divmod(self, other): The pair (self // other, self % other).
213194

Lib/test/test_builtin.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,13 +1456,12 @@ def test_pow(self):
14561456
else:
14571457
self.assertAlmostEqual(pow(x, y, z), 24.0)
14581458

1459-
self.assertAlmostEqual(pow(-1, 0.5), 1j)
1460-
self.assertAlmostEqual(pow(-1, 1./3), 0.5 + 0.8660254037844386j)
1461-
14621459
self.assertRaises(TypeError, pow, -1, -2, 3)
14631460
self.assertRaises(ValueError, pow, 1, 2, 0)
14641461
self.assertRaises(TypeError, pow, -1L, -2L, 3L)
14651462
self.assertRaises(ValueError, pow, 1L, 2L, 0L)
1463+
# Will return complex in 3.0:
1464+
self.assertRaises(ValueError, pow, -342.43, 0.234)
14661465

14671466
self.assertRaises(TypeError, pow)
14681467

@@ -1664,11 +1663,11 @@ def test_round(self):
16641663
self.assertEqual(type(round(-8.0, 0)), float)
16651664
self.assertEqual(type(round(-8.0, 1)), float)
16661665

1667-
# Check even / odd rounding behaviour
1666+
# Check half rounding behaviour.
16681667
self.assertEqual(round(5.5), 6)
1669-
self.assertEqual(round(6.5), 6)
1668+
self.assertEqual(round(6.5), 7)
16701669
self.assertEqual(round(-5.5), -6)
1671-
self.assertEqual(round(-6.5), -6)
1670+
self.assertEqual(round(-6.5), -7)
16721671

16731672
# Check behavior on ints
16741673
self.assertEqual(round(0), 0)
@@ -1686,22 +1685,21 @@ def test_round(self):
16861685

16871686
# test generic rounding delegation for reals
16881687
class TestRound(object):
1689-
def __round__(self):
1690-
return 23
1688+
def __float__(self):
1689+
return 23.0
16911690

16921691
class TestNoRound(object):
16931692
pass
16941693

16951694
self.assertEqual(round(TestRound()), 23)
16961695

16971696
self.assertRaises(TypeError, round, 1, 2, 3)
1698-
# XXX: This is not ideal, but see the comment in builtin_round().
1699-
self.assertRaises(AttributeError, round, TestNoRound())
1697+
self.assertRaises(TypeError, round, TestNoRound())
17001698

17011699
t = TestNoRound()
1702-
t.__round__ = lambda *args: args
1703-
self.assertEquals((), round(t))
1704-
self.assertEquals((0,), round(t, 0))
1700+
t.__float__ = lambda *args: args
1701+
self.assertRaises(TypeError, round, t)
1702+
self.assertRaises(TypeError, round, t, 0)
17051703

17061704
def test_setattr(self):
17071705
setattr(sys, 'spam', 1)

Lib/test/test_long.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -385,9 +385,7 @@ def test_float_overflow(self):
385385
"1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
386386
"math.sin(huge)", "math.sin(mhuge)",
387387
"math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
388-
# math.floor() of an int returns an int now
389-
##"math.floor(huge)", "math.floor(mhuge)",
390-
]:
388+
"math.floor(huge)", "math.floor(mhuge)"]:
391389

392390
self.assertRaises(OverflowError, eval, test, namespace)
393391

Lib/test/test_math.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ def testCeil(self):
6363
self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
6464

6565
class TestCeil(object):
66-
def __ceil__(self):
67-
return 42
66+
def __float__(self):
67+
return 41.3
6868
class TestNoCeil(object):
6969
pass
7070
self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
@@ -123,8 +123,8 @@ def testFloor(self):
123123
self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
124124

125125
class TestFloor(object):
126-
def __floor__(self):
127-
return 42
126+
def __float__(self):
127+
return 42.3
128128
class TestNoFloor(object):
129129
pass
130130
self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42)

Modules/mathmodule.c

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -107,28 +107,9 @@ FUNC1(atan, atan,
107107
FUNC2(atan2, atan2,
108108
"atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
109109
"Unlike atan(y/x), the signs of both x and y are considered.")
110-
111-
static PyObject * math_ceil(PyObject *self, PyObject *number) {
112-
static PyObject *ceil_str = NULL;
113-
PyObject *method;
114-
115-
if (ceil_str == NULL) {
116-
ceil_str = PyString_FromString("__ceil__");
117-
if (ceil_str == NULL)
118-
return NULL;
119-
}
120-
121-
method = _PyType_Lookup(Py_Type(number), ceil_str);
122-
if (method == NULL)
123-
return math_1(number, ceil);
124-
else
125-
return PyObject_CallFunction(method, "O", number);
126-
}
127-
128-
PyDoc_STRVAR(math_ceil_doc,
129-
"ceil(x)\n\nReturn the ceiling of x as a float.\n"
130-
"This is the smallest integral value >= x.");
131-
110+
FUNC1(ceil, ceil,
111+
"ceil(x)\n\nReturn the ceiling of x as a float.\n"
112+
"This is the smallest integral value >= x.")
132113
FUNC1(cos, cos,
133114
"cos(x)\n\nReturn the cosine of x (measured in radians).")
134115
FUNC1(cosh, cosh,
@@ -147,28 +128,9 @@ FUNC1(exp, exp,
147128
"exp(x)\n\nReturn e raised to the power of x.")
148129
FUNC1(fabs, fabs,
149130
"fabs(x)\n\nReturn the absolute value of the float x.")
150-
151-
static PyObject * math_floor(PyObject *self, PyObject *number) {
152-
static PyObject *floor_str = NULL;
153-
PyObject *method;
154-
155-
if (floor_str == NULL) {
156-
floor_str = PyString_FromString("__floor__");
157-
if (floor_str == NULL)
158-
return NULL;
159-
}
160-
161-
method = _PyType_Lookup(Py_Type(number), floor_str);
162-
if (method == NULL)
163-
return math_1(number, floor);
164-
else
165-
return PyObject_CallFunction(method, "O", number);
166-
}
167-
168-
PyDoc_STRVAR(math_floor_doc,
169-
"floor(x)\n\nReturn the floor of x as a float.\n"
170-
"This is the largest integral value <= x.");
171-
131+
FUNC1(floor, floor,
132+
"floor(x)\n\nReturn the floor of x as a float.\n"
133+
"This is the largest integral value <= x.")
172134
FUNC2(fmod, fmod,
173135
"fmod(x,y)\n\nReturn fmod(x, y), according to platform C."
174136
" x % y may differ.")

Objects/floatobject.c

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -986,10 +986,9 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
986986
* bugs so we have to figure it out ourselves.
987987
*/
988988
if (iw != floor(iw)) {
989-
/* Negative numbers raised to fractional powers
990-
* become complex.
991-
*/
992-
return PyComplex_Type.tp_as_number->nb_power(v, w, z);
989+
PyErr_SetString(PyExc_ValueError, "negative number "
990+
"cannot be raised to a fractional power");
991+
return NULL;
993992
}
994993
/* iw is an exact integer, albeit perhaps a very large one.
995994
* -1 raised to an exact integer should never be exceptional.
@@ -1098,54 +1097,6 @@ float_trunc(PyObject *v)
10981097
return PyLong_FromDouble(wholepart);
10991098
}
11001099

1101-
static PyObject *
1102-
float_round(PyObject *v, PyObject *args)
1103-
{
1104-
#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */
1105-
double x;
1106-
double f;
1107-
double flr, cil;
1108-
double rounded;
1109-
int i;
1110-
int ndigits = UNDEF_NDIGITS;
1111-
1112-
if (!PyArg_ParseTuple(args, "|i", &ndigits))
1113-
return NULL;
1114-
1115-
x = PyFloat_AsDouble(v);
1116-
1117-
if (ndigits != UNDEF_NDIGITS) {
1118-
f = 1.0;
1119-
i = abs(ndigits);
1120-
while (--i >= 0)
1121-
f = f*10.0;
1122-
if (ndigits < 0)
1123-
x /= f;
1124-
else
1125-
x *= f;
1126-
}
1127-
1128-
flr = floor(x);
1129-
cil = ceil(x);
1130-
1131-
if (x-flr > 0.5)
1132-
rounded = cil;
1133-
else if (x-flr == 0.5)
1134-
rounded = fmod(flr, 2) == 0 ? flr : cil;
1135-
else
1136-
rounded = flr;
1137-
1138-
if (ndigits != UNDEF_NDIGITS) {
1139-
if (ndigits < 0)
1140-
rounded *= f;
1141-
else
1142-
rounded /= f;
1143-
}
1144-
1145-
return PyFloat_FromDouble(rounded);
1146-
#undef UNDEF_NDIGITS
1147-
}
1148-
11491100
static PyObject *
11501101
float_float(PyObject *v)
11511102
{
@@ -1344,9 +1295,6 @@ static PyMethodDef float_methods[] = {
13441295
"Returns self, the complex conjugate of any float."},
13451296
{"__trunc__", (PyCFunction)float_trunc, METH_NOARGS,
13461297
"Returns the Integral closest to x between 0 and x."},
1347-
{"__round__", (PyCFunction)float_round, METH_VARARGS,
1348-
"Returns the Integral closest to x, rounding half toward even.\n"
1349-
"When an argument is passed, works like built-in round(x, ndigits)."},
13501298
{"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS},
13511299
{"__getformat__", (PyCFunction)float_getformat,
13521300
METH_O|METH_CLASS, float_getformat_doc},

0 commit comments

Comments
 (0)