Factorial
Algorithms
Programming Languages
Code Implementation
Computational Mathematics

Factorial Algorithms in different languages

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

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

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

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

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++

cpp
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

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

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

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.

Performance Comparison

LanguageMax with native intArbitrary precisionNotes
PythonUnlimited (int)Built-inmath.factorial is C-optimized
JavaScript20! (Number)BigIntBigInt slower than Number
Java20! (long)BigIntegerVerbose but capable
C++20! (uint64)External libraryCompile-time possible
Go20! (uint64)math/bigClean API
Rust34! (u128)num crateOverflow detection in debug
HaskellUnlimited (Integer)Built-inMost 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

Course illustration
Course illustration

All Rights Reserved.