Factorial
Algorithms
Programming Languages
Code Implementation
Computational Mathematics

Factorial Algorithms in different languages

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

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

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.