Efficient Factorial Calculation in Python: Recursive vs. Iterative Methods

  • Context: Python 
  • Thread starter Thread starter Whovian
  • Start date Start date
  • Tags Tags
    Bit Python
Click For Summary

Discussion Overview

The discussion revolves around the implementation of factorial calculations in Python, comparing recursive and iterative methods. Participants explore the efficiency of these approaches and address issues related to input validation and potential errors in the code.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant presents a recursive implementation of the factorial function and encounters an infinite recursion issue when negative inputs are provided.
  • Another participant points out the necessity of ensuring that the parameters satisfy the condition 0 ≤ r ≤ n to avoid errors in the calculation.
  • There is a suggestion to enhance the factorial function to validate against negative inputs and potentially raise exceptions for robustness in more complex applications.
  • A participant questions the efficiency of the recursive approach, suggesting that iterative methods may be more efficient in Python.
  • Two alternative implementations of factorial are provided: a recursive version and an iterative version, with timing comparisons indicating that the iterative method is faster.
  • One participant expresses a personal style preference against extensive input validation, suggesting that negative inputs should not occur in practice, although acknowledging that there are scenarios where validation might be necessary.

Areas of Agreement / Disagreement

Participants generally agree on the need for input validation and the inefficiency of the recursive method in Python, but there is no consensus on the extent of input validation required or the best approach to factorial calculation.

Contextual Notes

Limitations include the assumption that negative inputs should not occur in practice, which may not hold in all contexts. The discussion does not resolve the debate on the necessity of input validation or the optimal method for calculating factorials.

Whovian
Messages
651
Reaction score
3
I tried the following code:

Code:
def factorial(n):
    if (n == 0):
        return 1
    else:
        return n*factorial(n-1)

def ncr(n,r):
    return ((factorial(n))/(factorial(r)*factorial(n-r)))

number = 0

for n in range(100):
    for r in range(100):
        print ncr(n,r)

Basically, for all n and r from 1 to 100, it's supposed to print ##\binom{n}{r}##

Unfortunately, running from the command line, I get:

Code:
Traceback (most recent call last):
  File "Pythontest.py", line 14, in <module>
    print ncr(n,r)
  File "Pythontest.py", line 8, in ncr
    return ((factorial(n))/(factorial(r)*factorial(n-r)))
  File "Pythontest.py", line 5, in factorial
    return n*factorial(n-1)
  File "Pythontest.py", line 5, in factorial
    return n*factorial(n-1)
  File "Pythontest.py", line 5, in factorial
    return n*factorial(n-1)
 
Technology news on Phys.org
you have to have [itex]0 \le r \le n[/itex]. your definition of factorial goes into an infinite callback if [itex]n < 0[/itex].
 
Also, for general purposes...factorial is not defined for negative numbers, so, you should enhance your 'def factorial' and guard (validate) against negative numbers and possibly raise an exception, etc...you know, for when you use this def in a more complex program.
 
Dickfore said:
you have to have [itex]0 \le r \le n[/itex]. your definition of factorial goes into an infinite callback if [itex]n < 0[/itex].

Oh. Oops.

gsal said:
Also, for general purposes...factorial is not defined for negative numbers, so, you should enhance your 'def factorial' and guard (validate) against negative numbers and possibly raise an exception, etc...you know, for when you use this def in a more complex program.

Also sound advice.
 
May I ask why you are doing it recursively? It's not particularly efficient in Python when done that way.

Code:
def rfac (x):
    return x * rfac (x-1) if x > 0 else 1
    
def ifac (x):
    f = 1
    for i in range (1, x+1):
        f *= i
    return f

from timeit import Timer
print (Timer ("rfac(20)", "from __main__ import rfac")).timeit()
print (Timer ("ifac(20)", "from __main__ import ifac")).timeit()

$ python fac.py
10.4178638458
5.76771497726

There are much faster ways to compute it, if you search the web.

Edit: I am not sure I would check or throw for negative input. There's defensive programming, and there's paranoia. It should not happen in practice. I admit this is personal style. I understand there cases where it might (web app), but seriously ... use a precomputed lookup table of N! if it's a web app.
 

Similar threads

  • · Replies 19 ·
Replies
19
Views
2K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 11 ·
Replies
11
Views
1K
  • · Replies 18 ·
Replies
18
Views
2K
  • · Replies 15 ·
Replies
15
Views
2K
  • · Replies 34 ·
2
Replies
34
Views
6K
  • · Replies 7 ·
Replies
7
Views
5K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 3 ·
Replies
3
Views
2K