Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 231aad3

Browse files
bpo-37315: Deprecate accepting floats in math.factorial(). (GH-14147)
1 parent 1ce2656 commit 231aad3

5 files changed

Lines changed: 28 additions & 7 deletions

File tree

Doc/library/math.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ Number-theoretic and representation functions
7171
Return *x* factorial as an integer. Raises :exc:`ValueError` if *x* is not integral or
7272
is negative.
7373

74+
.. deprecated:: 3.9
75+
Accepting floats with integral values (like ``5.0``) is deprecated.
76+
7477

7578
.. function:: floor(x)
7679

Doc/whatsnew/3.9.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ Build and C API Changes
109109
Deprecated
110110
==========
111111

112+
* Currently :func:`math.factorial` accepts :class:`float` instances with
113+
non-negative integer values (like ``5.0``). It raises a :exc:`ValueError`
114+
for non-integral and negative floats. It is deprecated now. In future
115+
Python versions it will raise a :exc:`TypeError` for all floats.
116+
(Contributed by Serhiy Storchaka in :issue:`37315`.)
112117

113118

114119
Removed

Lib/test/test_math.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -501,21 +501,25 @@ def testFabs(self):
501501

502502
def testFactorial(self):
503503
self.assertEqual(math.factorial(0), 1)
504-
self.assertEqual(math.factorial(0.0), 1)
505504
total = 1
506505
for i in range(1, 1000):
507506
total *= i
508507
self.assertEqual(math.factorial(i), total)
509-
self.assertEqual(math.factorial(float(i)), total)
510508
self.assertEqual(math.factorial(i), py_factorial(i))
511509
self.assertRaises(ValueError, math.factorial, -1)
512-
self.assertRaises(ValueError, math.factorial, -1.0)
513510
self.assertRaises(ValueError, math.factorial, -10**100)
514-
self.assertRaises(ValueError, math.factorial, -1e100)
515-
self.assertRaises(ValueError, math.factorial, math.pi)
516511

517512
def testFactorialNonIntegers(self):
518-
self.assertRaises(TypeError, math.factorial, decimal.Decimal(5.2))
513+
with self.assertWarns(DeprecationWarning):
514+
self.assertEqual(math.factorial(5.0), 120)
515+
with self.assertWarns(DeprecationWarning):
516+
self.assertRaises(ValueError, math.factorial, 5.2)
517+
with self.assertWarns(DeprecationWarning):
518+
self.assertRaises(ValueError, math.factorial, -1.0)
519+
with self.assertWarns(DeprecationWarning):
520+
self.assertRaises(ValueError, math.factorial, -1e100)
521+
self.assertRaises(TypeError, math.factorial, decimal.Decimal('5'))
522+
self.assertRaises(TypeError, math.factorial, decimal.Decimal('5.2'))
519523
self.assertRaises(TypeError, math.factorial, "5")
520524

521525
# Other implementations may place different upper bounds.
@@ -524,7 +528,8 @@ def testFactorialHugeInputs(self):
524528
# Currently raises ValueError for inputs that are too large
525529
# to fit into a C long.
526530
self.assertRaises(OverflowError, math.factorial, 10**100)
527-
self.assertRaises(OverflowError, math.factorial, 1e100)
531+
with self.assertWarns(DeprecationWarning):
532+
self.assertRaises(OverflowError, math.factorial, 1e100)
528533

529534
def testFloor(self):
530535
self.assertRaises(TypeError, math.floor)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Deprecated accepting floats with integral value (like ``5.0``) in
2+
:func:`math.factorial`.

Modules/mathmodule.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,6 +1981,12 @@ math_factorial(PyObject *module, PyObject *arg)
19811981
PyObject *result, *odd_part, *pyint_form;
19821982

19831983
if (PyFloat_Check(arg)) {
1984+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
1985+
"Using factorial() with floats is deprecated",
1986+
1) < 0)
1987+
{
1988+
return NULL;
1989+
}
19841990
PyObject *lx;
19851991
double dx = PyFloat_AS_DOUBLE((PyFloatObject *)arg);
19861992
if (!(Py_IS_FINITE(dx) && dx == floor(dx))) {

0 commit comments

Comments
 (0)