The factorial function and its extension to the complex plane - the Gamma function are without doubt my favourite mathematical devices. In this blog post, I would like to shed some light on approximation methods for the Gamma function, as well as functions closely related to it (polygamma, digamma, etc…).
The Gamma function is canonically defined using an integral as follows:
Γ(z)=∫0∞tz−1e−tdt
The Gamma function is a generalization of the factorial function, therefore the following holds:
Γ(n+1)=n!
Since Γ(1)=1 and Γ(n+1)=nΓ(n), which follows from the integral definition.
Euler and Weierstrass respectively suggest the following infinite product expansions for the Gamma function (where γ is the Euler-Mascheroni constant), however they’re not that useful in practice:
Likely the most widely known formula for approximating the factorial function:
n!∼2πn(en)n
Stirling approximation is only ever useful for large values of n. It can be used to approximate the gamma function for positive real argument, and as a consequence of the reflection formula, negative real argument:
Γ(−z)=−2π(z+1)(ez+1)z+1πcsc(πz)
Because of how inaccurate the approximation is for smaller values, one can use the recurrence relation obtain a large argument.
Spouge’s approximation is a modification of Stirling’s approximation. It’s, in my opinion, the most efficient way to compute the values of the Gamma function when using arbitrary precision arithmetics. The formula follows:
My preferred method of approximating the digamma function for small arguments would be using McCullagh’s series. As an example of the first method, we will approximate Γ(x) using the Ramanujan approximation for (x−1)!
There are also simpler to compute asymptotic approximations for the digamma function, however, they’re not particularly useful because of their inaccuracy. For example:
ψ(x)∼lnx−2x1
Finally, the logarithmic derivative of the Spouge’s approximation also performs well. Temporarily fix f(z) as the coefficient term:
However, McCullagh’s series for the Digamma function let us solve this problem more elegantly:
ψ(z+1)=−γ−n=1∑∞(−z)n(dn+z+ncn)
Where the coefficients can be precomputed:
cn=nn1, dn=ζ(n+1,n+1)=k=n+1∑∞kn+11
The accuracy of McCullagh’s series is the best for ψ(1) and dimnishes as the argument grows.
For larger arguments, I use the digamma reflection formula to increase the argument and then use the asymptotic expansion:
publicstaticdoubledigamma(double x){double digamma =0;// Reflection:if(x <0){
digamma -=Math.PI /Math.tan(Math.PI * x);
x =1- x;}// Small enough arguments:if(x >0&& x <=1e-5)return digamma -0.577215664901532860606512090082-1/ x;// Increase argument:while(x <49){
digamma -=1/ x;
x +=1;}// Use asymptoticsfinaldouble inv =1/(x * x);
digamma +=Math.log(x)-0.5/ x + inv *(-1d/12+ inv *(1d/120-(1d/252)* inv));return digamma;}
Yang ZH, Tian JF. An accurate approximation formula for gamma function. J Inequal Appl. 2018;2018(1):56. doi: 10.1186/s13660-018-1646-6. Epub 2018 Mar 6. PMID: 29540975; PMCID: PMC5840229. ↩︎