Search code examples
javarecursionfactorial

Recursive function to compute factorial fails after 20


I've written the below Java code to compute factorial of numbers from 1 to 30 recursively. For some reason, the output doesn't match with the results here for numbers greater than 20. I am surprised to see negative numbers as well.

Code

class Test {
    
    public static Long factorial(Long number) {
        if(number == 1){
            return 1L;
        }else{
            return number*factorial(number-1);
        }
    }
    
    public static void main(final String... arguments){
        for(Long number=1L;number<=30;number++){
            System.out.println("Factorial of " + number + "  : " + factorial(number));
        }
    }
}

Output

Factorial of 1  : 1
Factorial of 2  : 2
Factorial of 3  : 6
Factorial of 4  : 24
Factorial of 5  : 120
Factorial of 6  : 720
Factorial of 7  : 5040
Factorial of 8  : 40320
Factorial of 9  : 362880
Factorial of 10  : 3628800
Factorial of 11  : 39916800
Factorial of 12  : 479001600
Factorial of 13  : 6227020800
Factorial of 14  : 87178291200
Factorial of 15  : 1307674368000
Factorial of 16  : 20922789888000
Factorial of 17  : 355687428096000
Factorial of 18  : 6402373705728000
Factorial of 19  : 121645100408832000
Factorial of 20  : 2432902008176640000
Factorial of 21  : -4249290049419214848
Factorial of 22  : -1250660718674968576
Factorial of 23  : 8128291617894825984
Factorial of 24  : -7835185981329244160
Factorial of 25  : 7034535277573963776
Factorial of 26  : -1569523520172457984
Factorial of 27  : -5483646897237262336
Factorial of 28  : -5968160532966932480
Factorial of 29  : -7055958792655077376
Factorial of 30  : -8764578968847253504

Could somebody please help me to compute factorial up to 30 correctly?


Solution

  • This is what's known as "overflow". Longs are stored with 64 bits; their maximum value is 2^63 - 1 which is 9,223,372,036,854,775,807. Instead try using a BigInteger. Using BigInteger is a bit tricky as instantiation and operations are different than normal int/longs. Here's your code reworked for BigInteger:

    public class BigIntFactorial {
    
        public static BigInteger factorial(BigInteger number) {
            if(number.equals(BigInteger.ONE)) {
                return BigInteger.valueOf(1);
            } else {
                return number.multiply(factorial(number.subtract(BigInteger.ONE)));
            }
        }
    
        public static void main(final String... arguments){
            for(Long number=1L;number<=30;number++){
    
                System.out.println("Factorial of " + number + "  : " + factorial(BigInteger.valueOf(number)));
            }
        }
    }
    

    output is:

    Factorial of 1  : 1
    Factorial of 2  : 2
    Factorial of 3  : 6
    Factorial of 4  : 24
    Factorial of 5  : 120
    Factorial of 6  : 720
    Factorial of 7  : 5040
    Factorial of 8  : 40320
    Factorial of 9  : 362880
    Factorial of 10  : 3628800
    Factorial of 11  : 39916800
    Factorial of 12  : 479001600
    Factorial of 13  : 6227020800
    Factorial of 14  : 87178291200
    Factorial of 15  : 1307674368000
    Factorial of 16  : 20922789888000
    Factorial of 17  : 355687428096000
    Factorial of 18  : 6402373705728000
    Factorial of 19  : 121645100408832000
    Factorial of 20  : 2432902008176640000
    Factorial of 21  : 51090942171709440000
    Factorial of 22  : 1124000727777607680000
    Factorial of 23  : 25852016738884976640000
    Factorial of 24  : 620448401733239439360000
    Factorial of 25  : 15511210043330985984000000
    Factorial of 26  : 403291461126605635584000000
    Factorial of 27  : 10888869450418352160768000000
    Factorial of 28  : 304888344611713860501504000000
    Factorial of 29  : 8841761993739701954543616000000
    Factorial of 30  : 265252859812191058636308480000000