[Python-checkins] bpo-35431: Drop the k <= n requirement (GH-13798)

Raymond Hettinger webhook-mailer at python.org
Tue Jun 4 04:23:27 EDT 2019


https://github.com/python/cpython/commit/963eb0f4738456455b9bef7eb531b46805415208
commit: 963eb0f4738456455b9bef7eb531b46805415208
branch: master
author: Raymond Hettinger <rhettinger at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2019-06-04T01:23:06-07:00
summary:

bpo-35431: Drop the k <= n requirement (GH-13798)

files:
M Doc/library/math.rst
M Lib/test/test_math.py
M Modules/clinic/mathmodule.c.h
M Modules/mathmodule.c

diff --git a/Doc/library/math.rst b/Doc/library/math.rst
index c5a77f1fab9f..4a1578972452 100644
--- a/Doc/library/math.rst
+++ b/Doc/library/math.rst
@@ -41,12 +41,15 @@ Number-theoretic and representation functions
    Return the number of ways to choose *k* items from *n* items without repetition
    and without order.
 
-   Also called the binomial coefficient. It is mathematically equal to the expression
-   ``n! / (k! (n - k)!)``. It is equivalent to the coefficient of the *k*-th term in the
-   polynomial expansion of the expression ``(1 + x) ** n``.
+   Evaluates to ``n! / (k! * (n - k)!)`` when ``k <= n`` and evaluates
+   to zero when ``k > n``.
 
-   Raises :exc:`TypeError` if the arguments not integers.
-   Raises :exc:`ValueError` if the arguments are negative or if *k* > *n*.
+   Also called the binomial coefficient because it is equivalent
+   to the coefficient of k-th term in polynomial expansion of the
+   expression ``(1 + x) ** n``.
+
+   Raises :exc:`TypeError` if either of the arguments not integers.
+   Raises :exc:`ValueError` if either of the arguments are negative.
 
    .. versionadded:: 3.8
 
@@ -212,10 +215,11 @@ Number-theoretic and representation functions
    Return the number of ways to choose *k* items from *n* items
    without repetition and with order.
 
-   It is mathematically equal to the expression ``n! / (n - k)!``.
+   Evaluates to ``n! / (n - k)!`` when ``k <= n`` and evaluates
+   to zero when ``k > n``.
 
-   Raises :exc:`TypeError` if the arguments not integers.
-   Raises :exc:`ValueError` if the arguments are negative or if *k* > *n*.
+   Raises :exc:`TypeError` if either of the arguments not integers.
+   Raises :exc:`ValueError` if either of the arguments are negative.
 
    .. versionadded:: 3.8
 
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py
index 96e0cf2fe671..86e3923af6d0 100644
--- a/Lib/test/test_math.py
+++ b/Lib/test/test_math.py
@@ -1904,9 +1904,9 @@ def testPerm(self):
         self.assertRaises(ValueError, perm, 1, -1)
         self.assertRaises(ValueError, perm, 1, -2**1000)
 
-        # Raises value error if k is greater than n
-        self.assertRaises(ValueError, perm, 1, 2)
-        self.assertRaises(ValueError, perm, 1, 2**1000)
+        # Returns zero if k is greater than n
+        self.assertEqual(perm(1, 2), 0)
+        self.assertEqual(perm(1, 2**1000), 0)
 
         n = 2**1000
         self.assertEqual(perm(n, 0), 1)
@@ -1970,9 +1970,9 @@ def testComb(self):
         self.assertRaises(ValueError, comb, 1, -1)
         self.assertRaises(ValueError, comb, 1, -2**1000)
 
-        # Raises value error if k is greater than n
-        self.assertRaises(ValueError, comb, 1, 2)
-        self.assertRaises(ValueError, comb, 1, 2**1000)
+        # Returns zero if k is greater than n
+        self.assertEqual(comb(1, 2), 0)
+        self.assertEqual(comb(1, 2**1000), 0)
 
         n = 2**1000
         self.assertEqual(comb(n, 0), 1)
diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h
index 0efe5cc409ce..cdf4305641b7 100644
--- a/Modules/clinic/mathmodule.c.h
+++ b/Modules/clinic/mathmodule.c.h
@@ -644,10 +644,11 @@ PyDoc_STRVAR(math_perm__doc__,
 "\n"
 "Number of ways to choose k items from n items without repetition and with order.\n"
 "\n"
-"It is mathematically equal to the expression n! / (n - k)!.\n"
+"Evaluates to n! / (n - k)! when k <= n and evaluates\n"
+"to zero when k > n.\n"
 "\n"
-"Raises TypeError if the arguments are not integers.\n"
-"Raises ValueError if the arguments are negative or if k > n.");
+"Raises TypeError if either of the arguments are not integers.\n"
+"Raises ValueError if either of the arguments are negative.");
 
 #define MATH_PERM_METHODDEF    \
     {"perm", (PyCFunction)(void(*)(void))math_perm, METH_FASTCALL, math_perm__doc__},
@@ -679,12 +680,15 @@ PyDoc_STRVAR(math_comb__doc__,
 "\n"
 "Number of ways to choose k items from n items without repetition and without order.\n"
 "\n"
-"Also called the binomial coefficient. It is mathematically equal to the expression\n"
-"n! / (k! * (n - k)!). It is equivalent to the coefficient of k-th term in\n"
-"polynomial expansion of the expression (1 + x)**n.\n"
+"Evaluates to n! / (k! * (n - k)!) when k <= n and evaluates\n"
+"to zero when k > n.\n"
 "\n"
-"Raises TypeError if the arguments are not integers.\n"
-"Raises ValueError if the arguments are negative or if k > n.");
+"Also called the binomial coefficient because it is equivalent\n"
+"to the coefficient of k-th term in polynomial expansion of the\n"
+"expression (1 + x)**n.\n"
+"\n"
+"Raises TypeError if either of the arguments are not integers.\n"
+"Raises ValueError if either of the arguments are negative.");
 
 #define MATH_COMB_METHODDEF    \
     {"comb", (PyCFunction)(void(*)(void))math_comb, METH_FASTCALL, math_comb__doc__},
@@ -709,4 +713,4 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=a82b0e705b6d0ec0 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5004266613284dcc input=a9049054013a1b77]*/
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 6e1099321c54..9a9a8159ced4 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -3007,15 +3007,16 @@ math.perm
 
 Number of ways to choose k items from n items without repetition and with order.
 
-It is mathematically equal to the expression n! / (n - k)!.
+Evaluates to n! / (n - k)! when k <= n and evaluates
+to zero when k > n.
 
-Raises TypeError if the arguments are not integers.
-Raises ValueError if the arguments are negative or if k > n.
+Raises TypeError if either of the arguments are not integers.
+Raises ValueError if either of the arguments are negative.
 [clinic start generated code]*/
 
 static PyObject *
 math_perm_impl(PyObject *module, PyObject *n, PyObject *k)
-/*[clinic end generated code: output=e021a25469653e23 input=f71ee4f6ff26be24]*/
+/*[clinic end generated code: output=e021a25469653e23 input=b2e7729d9a1949cf]*/
 {
     PyObject *result = NULL, *factor = NULL;
     int overflow, cmp;
@@ -3052,8 +3053,8 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k)
     cmp = PyObject_RichCompareBool(n, k, Py_LT);
     if (cmp != 0) {
         if (cmp > 0) {
-            PyErr_SetString(PyExc_ValueError,
-                            "k must be an integer less than or equal to n");
+            result = PyLong_FromLong(0);
+            goto done;
         }
         goto error;
     }
@@ -3121,18 +3122,21 @@ math.comb
 
 Number of ways to choose k items from n items without repetition and without order.
 
-Also called the binomial coefficient. It is mathematically equal to the expression
-n! / (k! * (n - k)!). It is equivalent to the coefficient of k-th term in
-polynomial expansion of the expression (1 + x)**n.
+Evaluates to n! / (k! * (n - k)!) when k <= n and evaluates
+to zero when k > n.
+
+Also called the binomial coefficient because it is equivalent
+to the coefficient of k-th term in polynomial expansion of the
+expression (1 + x)**n.
 
-Raises TypeError if the arguments are not integers.
-Raises ValueError if the arguments are negative or if k > n.
+Raises TypeError if either of the arguments are not integers.
+Raises ValueError if either of the arguments are negative.
 
 [clinic start generated code]*/
 
 static PyObject *
 math_comb_impl(PyObject *module, PyObject *n, PyObject *k)
-/*[clinic end generated code: output=bd2cec8d854f3493 input=2f336ac9ec8242f9]*/
+/*[clinic end generated code: output=bd2cec8d854f3493 input=9a05315af2518709]*/
 {
     PyObject *result = NULL, *factor = NULL, *temp;
     int overflow, cmp;
@@ -3173,9 +3177,8 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k)
     }
     if (Py_SIZE(temp) < 0) {
         Py_DECREF(temp);
-        PyErr_SetString(PyExc_ValueError,
-                        "k must be an integer less than or equal to n");
-        goto error;
+        result = PyLong_FromLong(0);
+        goto done;
     }
     cmp = PyObject_RichCompareBool(temp, k, Py_LT);
     if (cmp > 0) {



More information about the Python-checkins mailing list