Factorial
Learn how to calculate the factorial of a number in Python using loops, recursion, and more.
Factorial
Problem
The factorial of a number n is the product of all positive integers from 1 to n. It is written as n!.
0! = 1 (by definition)
1! = 1
2! = 2 × 1 = 2
3! = 3 × 2 × 1 = 6
4! = 4 × 3 × 2 × 1 = 24
5! = 5 × 4 × 3 × 2 × 1 = 120Input: 5
Output: 120
Input: 0
Output: 1
Input: 10
Output: 3628800Logic
- If
nis0or1— return1(base case) - Otherwise multiply
n × (n-1) × (n-2) × ... × 1 - Keep multiplying until you reach
1
Flow
Solution 1 — using a loop
Multiply from n down to 1, accumulating the result.
def factorial(n):
# factorial is not defined for negative numbers
if n < 0:
raise ValueError("Factorial is not defined for negative numbers.")
# base case — 0! = 1 by definition
if n == 0:
return 1
result = 1
# multiply result by every number from n down to 1
for i in range(n, 0, -1):
result *= i # result = result × i
return result
print(factorial(0)) # 1
print(factorial(1)) # 1
print(factorial(5)) # 120
print(factorial(10)) # 3628800Code Execution — Solution 1
Trace through factorial(5):
range(5, 0, -1) gives 5, 4, 3, 2, 1
| Step | i | result = result × i | result |
|---|---|---|---|
| Start | — | — | 1 |
| 1st | 5 | 1 × 5 | 5 |
| 2nd | 4 | 5 × 4 | 20 |
| 3rd | 3 | 20 × 3 | 60 |
| 4th | 2 | 60 × 2 | 120 |
| 5th | 1 | 120 × 1 | 120 |
| Done | 120 |
Trace through factorial(0):
n == 0 → immediately returns 1 without entering the loop.
Solution 2 — multiplying from 1 upward
Same idea — just loop from 1 to n instead of n down to 1. Same result either way.
def factorial(n):
if n < 0:
raise ValueError("Factorial is not defined for negative numbers.")
if n == 0:
return 1
result = 1
# multiply from 1 up to n
for i in range(1, n + 1):
result *= i
return result
print(factorial(5)) # 120
print(factorial(6)) # 720
print(factorial(10)) # 3628800Code Execution — Solution 2
Trace through factorial(5):
range(1, 6) gives 1, 2, 3, 4, 5
| Step | i | result = result × i | result |
|---|---|---|---|
| Start | — | — | 1 |
| 1st | 1 | 1 × 1 | 1 |
| 2nd | 2 | 1 × 2 | 2 |
| 3rd | 3 | 2 × 3 | 6 |
| 4th | 4 | 6 × 4 | 24 |
| 5th | 5 | 24 × 5 | 120 |
| Done | 120 |
Both Solution 1 and 2 give the same result — multiplication is commutative, so order does not matter.
Solution 3 — using recursion
Factorial is defined recursively — n! = n × (n-1)!. This maps perfectly to a recursive function.
def factorial(n):
if n < 0:
raise ValueError("Factorial is not defined for negative numbers.")
# base case — stop here
if n == 0 or n == 1:
return 1
# recursive case — n × factorial of (n-1)
return n * factorial(n - 1)
print(factorial(0)) # 1
print(factorial(1)) # 1
print(factorial(5)) # 120
print(factorial(10)) # 3628800Code Execution — Solution 3
Trace through factorial(5):
factorial(5)
= 5 × factorial(4)
= 4 × factorial(3)
= 3 × factorial(2)
= 2 × factorial(1)
= 1 ← base case
= 2 × 1 = 2
= 3 × 2 = 6
= 4 × 6 = 24
= 5 × 24 = 120The call stack builds up to factorial(1), then unwinds — each level multiplies its n by the result returned from below.
Every recursive function needs two things:
- Base case — the condition that stops the recursion. Here it is
n == 0 or n == 1. - Recursive case — the function calling itself with a smaller input. Here it is
n * factorial(n - 1).
Without the base case, the function would call itself forever — RecursionError.
Solution 4 — using math.factorial
Python's standard library has a built-in factorial function. Fastest and most reliable.
import math
print(math.factorial(0)) # 1
print(math.factorial(5)) # 120
print(math.factorial(10)) # 3628800
print(math.factorial(20)) # 2432902008176640000Solution 5 — using reduce()
Multiply all numbers from 1 to n together using reduce().
from functools import reduce
def factorial(n):
if n < 0:
raise ValueError("Factorial is not defined for negative numbers.")
if n == 0:
return 1
# reduce multiplies pairs left to right
# range(1, n+1) = 1, 2, 3, ..., n
return reduce(lambda a, b: a * b, range(1, n + 1))
print(factorial(5)) # 120
print(factorial(10)) # 3628800Code Execution — Solution 5
Trace through factorial(5):
range(1, 6) = [1, 2, 3, 4, 5]
reduce(lambda a, b: a * b, [1, 2, 3, 4, 5]):
| Step | a | b | a * b |
|---|---|---|---|
| 1st | 1 | 2 | 2 |
| 2nd | 2 | 3 | 6 |
| 3rd | 6 | 4 | 24 |
| 4th | 24 | 5 | 120 |
Result: 120
Bonus — factorial of large numbers
Python handles arbitrarily large integers natively — no overflow:
import math
print(math.factorial(50))
# 30414093201713378043612608166979581188299763898377856000000000000
print(math.factorial(100))
# 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000This is one of Python's great strengths — you never have to worry about integer overflow.
Recursive vs iterative — when to use which
| Approach | Pros | Cons |
|---|---|---|
| Loop | Fast, no call stack limit | Slightly more code |
| Recursion | Elegant, mirrors the definition | Slower, limited by recursion depth |
math.factorial | Fastest, built-in | No learning value |
reduce | Functional style | Less readable for beginners |
Python's default recursion limit is 1000 calls deep. factorial(1000) would cause a RecursionError with the recursive solution. Use the loop or math.factorial for large inputs.
Which solution to use?
| Solution | How | Best when |
|---|---|---|
| Solution 1 | Loop downward | Easy to understand |
| Solution 2 | Loop upward | Same thing, different direction |
| Solution 3 | Recursion | Learning recursion |
| Solution 4 | math.factorial | Real projects |
| Solution 5 | reduce() | Learning functional style |
Output
1
1
120
3628800