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.

Advertisement

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:

  1. Multiplies the current factorial by i.

  2. Increments i.

  3. Stops once i becomes 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 StackOverflowError occurs.


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 BigInteger whenever overflow is possible.

  • Prefer iteration over recursion for large inputs.

  • Remember that BigInteger objects 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 int and long.

  • Recommend BigInteger for 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.