Kelan
Kelan

Reputation: 371

How can I make my factorial method work with decimals? (Gamma)

I have a method that returns the factorial of the input. It works perfectly for integers, but I cant figure out how to make it work with decimal numbers.

Here is my method currently:

public static double factorial(double d)
{
    if (d == 0.0)
    {
        return 1.0;
    }

    double abs = Math.abs(d);
    double decimal = abs - Math.floor(abs);
    double result = 1.0;

    for (double i = Math.floor(abs); i > decimal; --i)
    {
        result *= (i + decimal);
    }
    if (d < 0.0)
    {
        result = -result;
    }

    return result;
}

I found an implementation but the code wasn't shown (I lost the link) and the example given was 5.5! = 5.5 * 4.5 * 3.5 * 2.5 * 1.5*0.5! = 287.885278

So from this pattern, I just added the decimal value to i in the for-loop result *= (i + decimal)

But clearly my logic is flawed

Edit: Just realsed that the last value is 0.5!, not 0.5. This makes all the difference. So 0.5! = 0.88622 and 5.5! = 5.5 * 4.5 * 3.5 * 2.5 * 1.5 * 0.88622 which equals 287.883028125

Upvotes: 3

Views: 2575

Answers (3)

Arcemo Gonsalez
Arcemo Gonsalez

Reputation: 9

There is a formula for this. All you need is some form of the Summation in calculus. It's explained in this video that I found: https://www.youtube.com/watch?v=v_HeaeUUOnc

In the formula, N is a value you set. The higher it is, the more accurate your factorial will be.

The formula is this

There is a java library that implements this, but here is a possible piece of code for the formula.

private double factorialInterpolation(int N, double x) {
        double total = 0d;
        
        for (int i = 1; i < N; i++) {
            total += Math.log((i / x + i));
        }
        
        total += x * Math.log(N);
        
        return total;
}
    
public double factorial(double x) {
        int N = 10000; // higher values gets more accuracy
        
        return Math.exp(factorialInterpolation(N, x));
}

Upvotes: 0

tucuxi
tucuxi

Reputation: 17955

The gamma function (which generalizes factorials to real numbers) is rather tricky to implement directly. Use a library such as apache-commons-math to calculate it for you, or look at their source to get a feel of what is involved. Once available, use as follows:

public static double generalizedFactorial(double d) {
    // Gamma(n) = (n-1)! for integer n
    return Gamma.gamma(d+1);
}

Outputs:

4.0! = 24.0
5.5! = 287.88527781504433
6.0! = 720.0

Previous answer (provides a factorial-like interpretation for real numbers > 1; but since there is already an aggreed-upon extension of factorial to real numbers, please disregard this for anything practical):

public static double f(double d) {
    double r = d - Math.floor(d) + 1;
    for (;d>1; d-=1) {
        r *= d;
    }
    return r;
}

Outputs:

4.0! = 24.0
5.5! = 487.265625
6.0! = 720.0

Upvotes: 5

xXliolauXx
xXliolauXx

Reputation: 1313

Factorial isn't actually defined for x€R, only for x€N. In words: you can't calculate the factorial of a decimal. (You can for 5.0, but not 5.1)

Edit: Thats the view for "traditional" factorial, for (really rarely needed) decimal factorial, see "gamma function".

Upvotes: 4

Related Questions