Introduction
The factorial of a non-negative integer n (written n!) is the product of all positive integers from 1 to n. Factorials appear in permutations, combinations, probability, and series expansions. Every language can compute factorials iteratively, recursively, or with built-in library functions. The key differences are how each language handles large integers, stack depth, and idiomatic style.
Python
1# Iterative
2def factorial_iter(n):
3 result = 1
4 for i in range(2, n + 1):
5 result *= i
6 return result
7
8# Recursive
9def factorial_rec(n):
10 if n <= 1:
11 return 1
12 return n * factorial_rec(n - 1)
13
14# Built-in (fastest, implemented in C)
15import math
16print(math.factorial(20)) # 2432902008176640000
17
18# Python handles arbitrarily large integers natively
19print(math.factorial(100)) # 158-digit number, no overflow
Python's math.factorial() is the best choice. It uses an optimized C implementation with divide-and-conquer multiplication for large numbers.
JavaScript
1// Iterative
2function factorial(n) {
3 let result = 1;
4 for (let i = 2; i <= n; i++) {
5 result *= i;
6 }
7 return result;
8}
9
10// Recursive
11function factorialRec(n) {
12 if (n <= 1) return 1;
13 return n * factorialRec(n - 1);
14}
15
16console.log(factorial(20)); // 2432902008176640000
17console.log(factorial(21)); // 51090942171709440000 (loses precision!)
18
19// BigInt for exact large factorials
20function factorialBig(n) {
21 let result = 1n;
22 for (let i = 2n; i <= n; i++) {
23 result *= i;
24 }
25 return result;
26}
27console.log(factorialBig(100n)); // Exact 158-digit result
JavaScript's Number type loses precision beyond 2^53. Use BigInt for factorials above 20.
Java
1// Iterative with long (max 20!)
2public static long factorial(int n) {
3 long result = 1;
4 for (int i = 2; i <= n; i++) {
5 result *= i;
6 }
7 return result;
8}
9
10// BigInteger for arbitrary precision
11import java.math.BigInteger;
12
13public static BigInteger factorialBig(int n) {
14 BigInteger result = BigInteger.ONE;
15 for (int i = 2; i <= n; i++) {
16 result = result.multiply(BigInteger.valueOf(i));
17 }
18 return result;
19}
20
21System.out.println(factorial(20)); // 2432902008176640000
22System.out.println(factorialBig(100)); // Exact 158-digit result
long overflows at 21!. Use BigInteger for values above 20.
C++
1#include <iostream>
2#include <numeric>
3#include <vector>
4
5// Iterative with unsigned long long (max 20!)
6unsigned long long factorial(int n) {
7 unsigned long long result = 1;
8 for (int i = 2; i <= n; i++) {
9 result *= i;
10 }
11 return result;
12}
13
14// Compile-time with constexpr (C++14)
15constexpr unsigned long long factorial_ct(int n) {
16 unsigned long long result = 1;
17 for (int i = 2; i <= n; i++) result *= i;
18 return result;
19}
20
21// Template metaprogramming (C++11)
22template<int N>
23struct Factorial {
24 static constexpr unsigned long long value = N * Factorial<N-1>::value;
25};
26template<>
27struct Factorial<0> {
28 static constexpr unsigned long long value = 1;
29};
30
31int main() {
32 std::cout << factorial(20) << std::endl; // 2432902008176640000
33 constexpr auto f = factorial_ct(20); // Computed at compile time
34 std::cout << Factorial<20>::value << std::endl; // Template version
35}
C++ has no built-in big integer. For n > 20, use a library like Boost.Multiprecision or implement your own.
Go
1package main
2
3import (
4 "fmt"
5 "math/big"
6)
7
8// Iterative (uint64, max 20!)
9func factorial(n uint64) uint64 {
10 result := uint64(1)
11 for i := uint64(2); i <= n; i++ {
12 result *= i
13 }
14 return result
15}
16
17// Big integer version
18func factorialBig(n int64) *big.Int {
19 result := big.NewInt(1)
20 for i := int64(2); i <= n; i++ {
21 result.Mul(result, big.NewInt(i))
22 }
23 return result
24}
25
26func main() {
27 fmt.Println(factorial(20)) // 2432902008176640000
28 fmt.Println(factorialBig(100)) // Exact 158-digit result
29}
Rust
1// Iterative (u128 gives up to 34!)
2fn factorial(n: u128) -> u128 {
3 (1..=n).product()
4}
5
6// Recursive with match
7fn factorial_rec(n: u128) -> u128 {
8 match n {
9 0 | 1 => 1,
10 _ => n * factorial_rec(n - 1),
11 }
12}
13
14fn main() {
15 println!("{}", factorial(20)); // 2432902008176640000
16 println!("{}", factorial(34)); // 295232799039604140847618609643520000000
17 // factorial(35) would overflow u128
18}
Rust panics on overflow in debug mode and wraps in release mode. Use the num crate for arbitrary precision.
Haskell
1-- Recursive (idiomatic)
2factorial :: Integer -> Integer
3factorial 0 = 1
4factorial n = n * factorial (n - 1)
5
6-- Using product and range
7factorial' :: Integer -> Integer
8factorial' n = product [1..n]
9
10-- Haskell's Integer type has arbitrary precision
11main = print (factorial 100) -- Exact 158-digit result
Haskell's lazy evaluation and arbitrary-precision Integer make factorial implementations concise and correct for any input size.
| Language | Max with native int | Arbitrary precision | Notes |
| Python | Unlimited (int) | Built-in | math.factorial is C-optimized |
| JavaScript | 20! (Number) | BigInt | BigInt slower than Number |
| Java | 20! (long) | BigInteger | Verbose but capable |
| C++ | 20! (uint64) | External library | Compile-time possible |
| Go | 20! (uint64) | math/big | Clean API |
| Rust | 34! (u128) | num crate | Overflow detection in debug |
| Haskell | Unlimited (Integer) | Built-in | Most concise |
Common Pitfalls
Integer overflow: 21! exceeds 64-bit integers. In C/C++/Java, overflow silently produces wrong results. Always check bounds or use big integer types.
Stack overflow with recursion: Recursive factorial hits the call stack limit around n=1000 in Python, n=10000 in Java. Use iterative versions for large n or enable tail-call optimization where supported.
Floating-point factorial: Using double loses precision after 18!. 170! is the largest representable as a double (beyond that, it returns infinity). Never use floats for exact factorial values.
Negative input: n! is undefined for negative integers. Guard against negative input. The gamma function extends factorials to non-integers but that is a different computation.
Performance for large n: Naive iteration is O(n) multiplications, but each multiplication grows with the size of the result. For very large n, divide-and-conquer multiplication (used by Python's math.factorial) is significantly faster.
Summary
Every language supports factorial via iteration or recursion
64-bit integers overflow at 21!, so use arbitrary-precision types for larger values
Python and Haskell handle big integers natively; other languages need special types
math.factorial() in Python is the fastest single-language option (C-optimized)
Prefer iterative implementations to avoid stack overflow with large inputs
C++ offers unique compile-time factorial computation via constexpr and templates