Ramanujan came up with an approximation for factorial that resembles Stirling’s famous approximation but is much more accurate.
As with Stirling’s approximation, the relative error in Ramanujan’s approximation decreases as n gets larger. Typically these approximations are not useful for small values of n. For n = 5, Stirling’s approximation gives 118.02 while the exact value is 120. But Ramanujan’s approximation gives 120.00015.
Here’s an implementation of the approximation in Python.
def ramanujan(x): fact = sqrt(pi)*(x/e)**x fact *= (((8*x + 4)*x + 1)*x + 1/30.)**(1./6.) return fact
For non-integer values of x, the function returns an approximation for Γ(x+1), an extension of factorial to real values. Here’s a plot of the accuracy of Ramanujan’s approximation.
For x = 50, Ramanujan’s approximation is good to nearly 10 significant figures, whereas Stirling’s approximation is good to about 7.
Here’s a little trickier implementation.
def ramanujan2(x): fact = sqrt(pi)*(x/e)**x fact *= (((8*x + 4)*x + 1)*x + 1/30.)**(1./6.) if isinstance(x, int): fact = int(fact) return fact
This code gives the same value as before if x is not an integer. But it gives exact values of factorial for x = 0, 1, 2, … 10. If x is 11 or greater, the result is not exact, but the relative error is less than 10^-7 and decreases as x increases. Ramanujan’s approximation always errs on the high side, so rounding the result down improves the accuracy and makes it exact for small integer inputs.
The downside of this trick is that now, for example,
ramanujan2(5.0) give different results. In some contexts, the improved accuracy may not be worth the inconsistency.
Reference: On Gosper’s formula for the Gamma function