If you need to calculate factorials in Java and you like sane programs that do not explode at runtime, welcome. This guide shows the math idea, two common implementations, when the runtime will throw a tiny tantrum, and how to handle very large results with BigInteger. Witty commentary included at no extra cost.
What factorial means in plain English
Factorial of n is n times n minus one times n minus two and so on until you hit one. By definition 0 factorial equals 1. That simple rule drives every implementation choice you will make here.
Iterative implementation for the practical developer
The iterative approach uses a loop to accumulate a product. It reads like assembly line work and it is memory friendly. Time complexity is O(n) and space complexity is O(1) apart from the variables you use.
// iterative factorial pseudocode for clarity and copy paste pity
static long factorialIterative(int n) {
if (n < 0) throw new IllegalArgumentException("negative input")
long result = 1
for (int i = 2; i <= n; i++) {
result *= i
}
return result
}
Use the iterative loop when input size can grow. It will not eat stack frames and it is predictable. Also remember that a 64 bit long overflows at 21 factorial so stop trusting long after 20 factorial.
Recursive implementation for the elegant but fragile
Recursion expresses factorial in self referential math style. It looks cute on whiteboards and is great for teaching. Both recursion and iteration take linear time. The kicker is stack usage. Java does not do tail call optimization so each recursive call consumes a stack frame and very large n will trigger a StackOverflowError.
// recursive factorial pseudocode that reads like math
static long factorialRecursive(int n) {
if (n < 0) throw new IllegalArgumentException("negative input")
if (n == 0 || n == 1) return 1
return n * factorialRecursive(n - 1)
}
Recursion is fine when n is small and clarity matters. For production where n might grow, favor the iterative version unless you like debugging stack traces at 2 am.
Performance and risks
- Time complexity for both methods is O(n)
- Iterative approach uses constant extra space
- Recursive approach uses O(n) stack frames and can cause StackOverflowError for large n
- Primitive long holds values up to 9,223,372,036,854,775,807 so factorials above 20 will overflow long
How to handle huge factorials with BigInteger
When you want exact results beyond 20 factorial use java.math.BigInteger. It handles arbitrary precision arithmetic but costs CPU and memory. For most uses you will prefer iterative multiplication with BigInteger because it is simple and robust.
// iterative factorial using BigInteger pseudocode
static BigInteger factorialBigInteger(int n) {
if (n < 0) throw new IllegalArgumentException("negative input")
BigInteger result = BigInteger.ONE
for (int i = 2; i <= n; i++) {
result = result.multiply(BigInteger.valueOf(i))
}
return result
}
Testing tips and edge cases
- Check zero and one, both should return 1
- Reject or handle negative inputs explicitly to avoid mysterious behavior
- Verify boundary around 20 factorial when using long
- For BigInteger check performance and memory when n grows large
Rules of thumb for mortal programmers
- Use iteration for production when n can grow and you need stability
- Use recursion for teaching, small n, or when you enjoy elegant code and the occasional StackOverflowError story
- Use BigInteger for correctness when results exceed 64 bit range
There you go. Now you can write factorial code that does not surprise anyone except the intern who thought recursion would scale forever. Go forth and compute responsibly.