How to find the factorial of a given number?

This is the complete solution to find the factorial of a given number. This solution is designed to solve the problem using an interface, super class and three derived classes implementing the interface.

package pack1;

import java.math.BigInteger;
 
public interface FactorialOfNumIntf {
 
    /* Define the functional interface with SAM 'RdInput' */
    public BigInteger RdInput(BigInteger intVal);
 
    /* Define the static method 'displayMsg' */
    static void displayMsg(BigInteger inpVal, BigInteger factorial) {
 
        BigInteger notExistFlagValue = BigInteger.valueOf(-1);
        if (factorial.compareTo(notExistFlagValue) != 0)
            System.out.println("\nFactorial of "+inpVal +" is " + factorial);
        else
            System.out.println("Factorial of Null not exits");
    }
}
package pack1;
 
import java.math.BigInteger;
import java.util.Optional;
import java.util.logging.Logger;
import java.util.stream.LongStream;
 
class NumberInput {
 
    private BigInteger inputIntvalue;
 
    /* Declare the logger object for the class to display the log messages */
    static Logger logger = Logger.getLogger(NumberInput.class.getName());
 
    public boolean validateInputs(BigInteger inputAnInteger) {
 
        /* Fetch the class object's name from which this method is called */
        String cName = Thread.currentThread().getStackTrace()[2].getClassName();
        String mName = "validateInputs()";
        logger.info("This method '" + mName + "' called from the Class '" + cName + "'");
 
        /* Validating the function parameters using Optional Integer Array data type */
        Optional<BigInteger> inputVal = Optional.ofNullable(inputAnInteger);
 
        /*
         * Fetch the value of the Optional Integer inputAnInteger using 'isPresent'
         * condition check. If the value is available use 'get' method otherwise simply
         * return 'false' to stop the program execution without proceeding further.
         */
        if (inputVal.isPresent())
            setInputIntvalue(inputVal.get());
        else
            return false;
 
        logger.info("The provided Input validated Successfully");
        return true;
    }
 
    /* Define getter and setters for an inputIntvalue BigInteger variable */
    public BigInteger getInputIntvalue() {
        return inputIntvalue;
    }
 
    public void setInputIntvalue(BigInteger inputIntvalue) {
        this.inputIntvalue = inputIntvalue;
    }
}
 
class FactorialOfNum_Using_CoreLogic extends NumberInput implements FactorialOfNumIntf {
 
    public BigInteger RdInput(BigInteger inpVal) {
 
        /* Fetch the class object's name from which this method is called */
        String cName = Thread.currentThread().getStackTrace()[2].getClassName();
        String mName = "RdInput";
        logger.info("This method '" + mName + "' called from the Class '" + cName + "'");
 
        /* Define a BigInteger variable and initialize factValue value to 1 */
        BigInteger factValue = new BigInteger("1");
 
        if (validateInputs(inpVal)) {
 
            for (int i = 2; BigInteger.valueOf(i).compareTo(getInputIntvalue()) <= 0; i++)
                factValue = factValue.multiply(BigInteger.valueOf(i));
        } else {
            logger.info("The given Input number is null");
            factValue = BigInteger.valueOf(-1);
        }
        FactorialOfNumIntf.displayMsg(inpVal, factValue);
        return factValue;
    }
}
 
class FactorialOfNum_Using_Recursion extends NumberInput implements FactorialOfNumIntf {
 
    public BigInteger RdInput(BigInteger inpVal) {
 
        /* Fetch the class object's name from which this method is called */
        String cName = Thread.currentThread().getStackTrace()[2].getClassName();
        String mName = "RdInput";
        logger.info("This method '" + mName + "' called from the Class '" + cName + "'");
 
        /* Define a BigInteger variable and initialize factValue value to 1 */
        BigInteger factValue = new BigInteger("1");
 
        if (validateInputs(inpVal))
            factValue = factRecursion(getInputIntvalue());
        else {
            logger.info("The given Input number is null");
            factValue = BigInteger.valueOf(-1);
        }
        FactorialOfNumIntf.displayMsg(inpVal, factValue);
        return factValue;
    }
 
    private static BigInteger factRecursion(BigInteger inpNum) {
 
        /* This is an exit condition to stop the recursion */
        if (inpNum == BigInteger.valueOf(0) || inpNum == BigInteger.valueOf(1))
            return BigInteger.valueOf(1);
        else
            return (inpNum.multiply(factRecursion(inpNum.subtract(BigInteger.valueOf(1)))));
    }
}
 
class FactorialOfNum_Using_Stream extends NumberInput implements FactorialOfNumIntf {
 
    public BigInteger RdInput(BigInteger inpVal) {
 
        /* Fetch the class object's name from which this method is called */
        String cName = Thread.currentThread().getStackTrace()[2].getClassName();
        String mName = "RdInput";
        logger.info("This method '" + mName + "' called from the Class '" + cName + "'");
        /*
         * Define a long integer variable and initialize factValue value to 1
         */
        long factValue = 1;
 
        if (validateInputs(inpVal)) {
 
            int iVal = getInputIntvalue().intValue();
            factValue = LongStream.range(1, iVal + 1).reduce(1, (a, b) -> (a * b));
        } else {
            logger.info("The given Input number is null");
            factValue = -1;
        }
        FactorialOfNumIntf.displayMsg(inpVal, BigInteger.valueOf(factValue));
        return BigInteger.valueOf(factValue);
    }
}
 
public class FactorialOfNumJ8 {
 
    public static void main(String args[]) {
 
        /*
         * create the class object FactorialOfNum_Using_CoreLogic, and call the method
         * RdInput
         */
 
        FactorialOfNum_Using_CoreLogic FNUCL = new FactorialOfNum_Using_CoreLogic();
        FNUCL.RdInput(BigInteger.valueOf(10));
        FNUCL.RdInput(null);
 
        /*
         * create the class object FactorialOfNum_Using_Recursion, and call the method
         * RdInput
         */
 
        FactorialOfNum_Using_Recursion FNUR = new FactorialOfNum_Using_Recursion();
        FNUR.RdInput(BigInteger.valueOf(15));
        FNUR.RdInput(null);
 
        /*
         * create the class object FactorialOfNum_Using_Stream, and call the method
         * RdInput
         */
 
        FactorialOfNum_Using_Stream FNUS = new FactorialOfNum_Using_Stream();
        FNUS.RdInput(BigInteger.valueOf(19));
        FNUS.RdInput(null);
    }
}
OUTPUT:
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_CoreLogic RdInput
INFO: This method 'RdInput' called from the Class 'pack1.FactorialOfNumJ8'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: This method 'validateInputs()' called from the Class 'pack1.FactorialOfNum_Using_CoreLogic'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: The provided Input validated Successfully

Factorial of 10 is 3628800
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_CoreLogic RdInput
INFO: This method 'RdInput' called from the Class 'pack1.FactorialOfNumJ8'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: This method 'validateInputs()' called from the Class 'pack1.FactorialOfNum_Using_CoreLogic'
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_CoreLogic RdInput
INFO: The given Input number is null
Factorial of Null not exits
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_Recursion RdInput
INFO: This method 'RdInput' called from the Class 'pack1.FactorialOfNumJ8'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: This method 'validateInputs()' called from the Class 'pack1.FactorialOfNum_Using_Recursion'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: The provided Input validated Successfully

Factorial of 15 is 1307674368000
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_Recursion RdInput
INFO: This method 'RdInput' called from the Class 'pack1.FactorialOfNumJ8'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: This method 'validateInputs()' called from the Class 'pack1.FactorialOfNum_Using_Recursion'
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_Recursion RdInput
INFO: The given Input number is null
Factorial of Null not exits
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_Stream RdInput
INFO: This method 'RdInput' called from the Class 'pack1.FactorialOfNumJ8'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: This method 'validateInputs()' called from the Class 'pack1.FactorialOfNum_Using_Stream'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: The provided Input validated Successfully

Factorial of 19 is 121645100408832000
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_Stream RdInput
INFO: This method 'RdInput' called from the Class 'pack1.FactorialOfNumJ8'
Mar 31, 2023 9:40:27 PM pack1.NumberInput validateInputs
INFO: This method 'validateInputs()' called from the Class 'pack1.FactorialOfNum_Using_Stream'
Mar 31, 2023 9:40:27 PM pack1.FactorialOfNum_Using_Stream RdInput
INFO: The given Input number is null
Factorial of Null not exits

The link to the JUnit5 test for this solution is here – https://atomic-temporary-185308886.wpcomstaging.com/2023/03/27/junit-test-code-factorial/