Introduction
Factorial is one of the most fundamental mathematical concepts you'll encounter while learning Java programming. Although the program itself is simple, it introduces several important programming concepts, including loops, recursion, integer overflow, and Java's BigInteger class.
Factorials are widely used in mathematics, statistics, probability, permutations, combinations, and many algorithmic problems. Because of their practical importance, finding the factorial of a number is one of the most common programming and interview questions.
In this guide, you'll learn four different ways to calculate factorials in Java, understand how each method works internally, handle important edge cases such as 0! and negative numbers, and learn when to use BigInteger instead of primitive data types.
What Is a Factorial?
The factorial of a non-negative integer n, represented as n!, is the product of all positive integers from 1 to n.
For example:
5! = 5 × 4 × 3 × 2 × 1 = 120
Another important mathematical rule is:
0! = 1
Factorials are commonly used in:
-
Permutations
-
Combinations
-
Probability calculations
-
Statistics
-
Dynamic programming
-
Combinatorial algorithms
Method 1: Using a For Loop
The for-loop approach is the most common and beginner-friendly solution.
Java Program
public class FactorialNumber {
public static void main(String[] args) {
int num = 5;
int fact = 1;
for (int i = 1; i <= num; i++) {
fact = fact * i;
}
System.out.println("Factorial of " + num + " is: " + fact);
}
}
Output
Factorial of 5 is: 120
Step-by-Step Execution
| Iteration | i | fact Before | Calculation | fact After |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 × 1 | 1 |
| 2 | 2 | 1 | 1 × 2 | 2 |
| 3 | 3 | 2 | 2 × 3 | 6 |
| 4 | 4 | 6 | 6 × 4 | 24 |
| 5 | 5 | 24 | 24 × 5 | 120 |
Why Does fact Start With 1?
The multiplicative identity is 1.
If you initialize:
int fact = 0;
then every multiplication becomes:
0 × anything = 0
and the final answer will always remain zero.
Time Complexity
O(n)
Space Complexity
O(1)
Method 2: Using a While Loop
The same logic can also be implemented using a while loop.
Java Program
public class FactorialWhileLoop {
public static void main(String[] args) {
int num = 5;
int fact = 1;
int i = 1;
while (i <= num) {
fact = fact * i;
i++;
}
System.out.println("Factorial of " + num + " is: " + fact);
}
}
Output
Factorial of 5 is: 120
How It Works
The loop repeatedly:
-
Multiplies the current factorial by
i. -
Increments
i. -
Stops once
ibecomes greater than the input number.
Functionally, this is identical to the for-loop solution.
Time Complexity
O(n)
Space Complexity
O(1)
Method 3: Using Recursion
Factorial is naturally defined recursively.
n! = n × (n−1)!
Base cases:
0! = 1
1! = 1
Java Program
public class FactorialRecursion {
static int factorial(int n) {
if (n == 0 || n == 1) {
return 1;
}
return n * factorial(n - 1);
}
public static void main(String[] args) {
int num = 5;
System.out.println("Factorial of " + num + " is: " + factorial(num));
}
}
Output
Factorial of 5 is: 120
Recursive Call Flow
factorial(5)
↓
5 × factorial(4)
↓
5 × 4 × factorial(3)
↓
5 × 4 × 3 × factorial(2)
↓
5 × 4 × 3 × 2 × factorial(1)
↓
5 × 4 × 3 × 2 × 1
↓
120
Each recursive call waits for the next call to finish before returning its result.
Time Complexity
O(n)
Space Complexity
O(n)
because every recursive call occupies one stack frame.
Method 4: Using BigInteger
Primitive data types have limited capacity.
| Data Type | Maximum Safe Factorial |
|---|---|
| int | 12! |
| long | 20! |
Beyond these values, integer overflow occurs.
Java's BigInteger class solves this problem.
Java Program
import java.math.BigInteger;
public class FactorialBigInteger {
public static void main(String[] args) {
int num = 25;
BigInteger fact = BigInteger.ONE;
for (int i = 1; i <= num; i++) {
fact = fact.multiply(BigInteger.valueOf(i));
}
System.out.println("Factorial of " + num + " is: " + fact);
}
}
Output
Factorial of 25 is:
15511210043330985984000000
Why BigInteger?
Unlike primitive data types, BigInteger has no fixed size.
It can store numbers limited only by the available system memory.
Time Complexity
Approximately O(n × multiplication cost)
Space Complexity
Depends on the size of the resulting number.
Handling Special Cases
Case 1: Factorial of Zero
By definition:
0! = 1
Fortunately, the iterative solutions handle this automatically.
Example:
int fact = 1;
for (int i = 1; i <= 0; i++) {
...
}
The loop never executes.
The value remains 1, which is correct.
Case 2: Negative Numbers
Factorial is not defined for negative integers.
Always validate the input before calculation.
if (num < 0) {
throw new IllegalArgumentException(
"Factorial is not defined for negative numbers."
);
}
Without this validation:
-
Loop-based solutions incorrectly return 1.
-
Recursive solutions continue indefinitely until a
StackOverflowErroroccurs.
How Java Handles This Internally
For Loop and While Loop
Variables:
num
fact
i
are primitive integers stored in the method's stack frame.
No objects are created.
Each iteration simply updates these values.
Recursive Method
Every recursive call creates a new stack frame containing:
-
current value of
n -
return address
-
local variables
When the base case is reached, the stack begins unwinding.
BigInteger Method
BigInteger is an immutable object.
Each call to:
fact.multiply(...)
creates a new BigInteger object.
Therefore, you must assign the result back:
fact = fact.multiply(...);
Real-Life Analogy
Imagine arranging five different books on a shelf.
For the first position, you have five choices.
After placing one book:
-
four choices remain for the second position,
-
then three,
-
then two,
-
then one.
Total arrangements:
5 × 4 × 3 × 2 × 1 = 120
This is exactly what factorial represents.
Comparison Table
| Method | Maximum Safe Input | Handles 0! | Best Used When |
|---|---|---|---|
| For Loop | 12! (int) | ✅ | Interviews and production code |
| While Loop | 12! (int) | ✅ | Same logic using while |
| Recursion | 12! (int) | ✅ | Learning recursion |
| BigInteger | Memory limit | ✅ | Large factorials like 50!, 100!, 500! |
Best Practices
-
Use the for-loop solution for everyday programming.
-
Validate negative inputs before calculation.
-
Switch to
BigIntegerwhenever overflow is possible. -
Prefer iteration over recursion for large inputs.
-
Remember that
BigIntegerobjects are immutable.
Common Mistakes
Initializing Factorial to Zero
Incorrect:
int fact = 0;
Every multiplication remains zero.
Always initialize with:
int fact = 1;
Ignoring Negative Numbers
Factorial is undefined for negative integers.
Always validate the input.
Using int for Large Numbers
13! = 6227020800
This exceeds the maximum value of an int.
Overflow occurs silently.
Forgetting BigInteger Assignment
Incorrect:
fact.multiply(BigInteger.valueOf(i));
Correct:
fact = fact.multiply(BigInteger.valueOf(i));
Using Recursion for Very Large Inputs
Large recursive calls consume stack memory and may result in:
StackOverflowError
Expert Tips
-
The iterative solution is usually preferred in production.
-
Mention recursion only as an alternative approach.
-
Discuss integer overflow when using
intandlong. -
Recommend
BigIntegerfor factorials beyond primitive limits. -
Always mention that factorial is undefined for negative numbers.
Pros and Cons
| Method | Advantages | Disadvantages |
|---|---|---|
| For Loop | Simple, fast, no recursion | Limited by integer overflow |
| While Loop | Same performance as for-loop | Slightly more verbose |
| Recursion | Elegant and close to the mathematical definition | Uses additional stack memory |
| BigInteger | Supports arbitrarily large factorials | Slower and more verbose |
Frequently Asked Questions
What is the easiest way to calculate factorial in Java?
Use a for loop that multiplies numbers from 1 to the given number.
What is 0 factorial?
By definition:
0! = 1
Can factorial be calculated using recursion?
Yes.
The recursive formula is:
factorial(n) = n × factorial(n − 1)
with base cases:
factorial(0) = 1
factorial(1) = 1
Why do I get negative answers for larger numbers?
Integer overflow.
Primitive types cannot store very large factorial values.
How can I calculate 50! or 100!?
Use Java's BigInteger class.
Is factorial defined for negative numbers?
No.
Negative integers do not have factorial values.
What is the time complexity?
All standard approaches require:
O(n)
multiplications.
Why does recursion sometimes throw StackOverflowError?
Because every recursive call uses stack memory.
Very large recursion depths eventually exceed the JVM stack size.
How many factorial values fit inside an int?
Up to:
12! = 479001600
Starting from 13!, integer overflow occurs.
Where is factorial used?
Factorials are widely used in:
-
Permutations
-
Combinations
-
Probability
-
Statistics
-
Dynamic programming
-
Mathematical algorithms
Is BigInteger slower than int?
Yes.
However, it guarantees correct results for very large numbers.
Can factorial values be cached?
Yes.
Memoization or precomputing factorials can significantly improve performance when the same factorial values are required repeatedly.