previous To the Homepage of Factorial Algorithms

Approximation Formulas
for the Factorial Function n!

We give an overview of approximations for the factorial function, convergent or asymptotic, old or new, compare their efficiency and give hints for their application.
Although most formulas are variations of the asymptotic expansion of James Stirling (1692–1770) we will reach a conclusion different from those given in most places.

Some abbreviations:
kern0(n) = sqrt(2Pi/n)*(n/e)^n = kern2(n)/sqrt(n)
kern1(n) = sqrt(2Pi*n)*(n/e)^n = kern2(n)*sqrt(n)
kern2(n) = sqrt(2Pi  )*(n/e)^n = sqrt(2Pi)*n^n*exp(-n) = sqrt(2Pi)*exp(n*(log(n)-1))  

kern0 - approximations

 stieltjes0(n) : N=n+1; kern0(N) 
 stieltjes1(n) : N=n+1; kern0(N)*exp((1/12)/N)
 stieltjes2(n) : N=n+1; kern0(N)*exp((1/12)/(N+(1/30)/N)) 
 stieltjes3(n) : N=n+1; kern0(N)*exp((1/12)/(N+(1/30)/(N+(53/210)/N)))  
 stieltjes4(n) : N=n+1; kern0(N)*exp((1/12)/(N+(1/30)/(N+(53/210)/(N+(195/371)/N))))
 
 henrici0(n)   : N=n+1; kern0(N) 
 henrici1(n)   : N=n+1; kern0(N)*exp(1/(12*N+1/N)) 
 henrici2(n)   : N=n+1; kern0(N)*exp(5/2*1/(30*N+1/N))
 henrici3(n)   : N=n+1; kern0(N)*exp((315*N-53/N)/(3780*N^2-510-53/N^2))
 
 stirser0(n)   : N=n+1; kern0(N) 
 stirser1(n)   : N=n+1; kern0(N)*exp(1/(12*N)) 
 stirser2(n)   : N=n+1; kern0(N)*exp(1/(12*N)*(1-1/(30*N^2))) 
 stirser3(n)   : N=n+1; kern0(N)*exp(1/(12*N)*(1-1/(30*N^2)*(1-2/(7*N^2))))  

kern1 - approximations

 ramanujan0(n):        kern1(n)
 ramanujan1(n): N=2*n; kern1(n)*(1+1/N)^(1/6)
 ramanujan2(n): N=2*n; kern1(n)*(1+1/N*(1+1/(2*N)))^(1/6) 
 ramanujan3(n): N=2*n; kern1(n)*(1+1/N*(1+1/(2*N)*(1+1/(15*N))))^(1/6) 
 ramanujan4(n): N=2*n; kern1(n)*(1+1/N*(1+1/(2*N)*(1+1/(15*N)*(1-11/(4*N)))))^(1/6) 
 ramanujan5(n): N=2*n; kern1(n)*(1+1/N*(1+1/(2*N)*(1+1/(15*N)*(1-1/(4*N)*(11-79/(7*N))))))^(1/6)

 ______ L0(n) :        kern1(n)
 ______ L1(n) : N=6*n; kern1(n)*(1+1/N)^(1/2) 
 ______ L2(n) : N=6*n; kern1(n)*(1+1/N*(1+1/(2*N)))^(1/2)
 ______ L3(n) : N=6*n; kern1(n)*(1+1/N*(1+1/(2*N)*(1-31/(15*N))))^(1/2)
 ______ L4(n) : N=6*n; kern1(n)*(1+1/N*(1+1/(2*N)*(1-1/(15*N)*(31+139/(4*N)))))^(1/2)
 ______ L5(n) : N=6*n; kern1(n)*(1+1/N*(1+1/(2*N)*(1-1/(15*N)*(31+1/(4*N)*(139-9871/(7*N))))))^(1/2) 
 
 stirling0(n) :         kern1(n) 
 stirling1(n) : N=12*n; kern1(n)*(1+1/N) 
 stirling2(n) : N=12*n; kern1(n)*(1+1/N*(1+1/(2*N))) 
 stirling3(n) : N=12*n; kern1(n)*(1+1/N*(1+1/(2*N)*(1-139/(15*N)))) 
 stirling4(n) : N=12*n; kern1(n)*(1+1/N*(1+1/(2*N)*(1-1/(15*N)*(139+571/(4*N)))))
 
 nemes0(n)  :           kern1(n) 
 nemes1(n)  : N=12*n^2; kern1(n)*(1+1/N)^n 
 nemes2(n)  : N=12*n^2; kern1(n)*(1+1/N*(1+1/(10*N)))^n 
 nemes3(n)  : N=12*n^2; kern1(n)*(1+1/N*(1+1/(10*N)*(1+239/(21*N))))^n 
 nemes4(n)  : N=12*n^2; kern1(n)*(1+1/N*(1+1/(10*N)*(1+1/(21*N)*(239-46409/(20*N)))))^n 
 
 nemesCF0(n) : kern1(n) 
 nemesCF1(n) : kern1(n)*(n/(n-1/12*1/n))^n
 nemesCF2(n) : kern1(n)*(n/(n-1/12*1/(n+3/40*1/n)))^n
 nemesCF3(n) : kern1(n)*(n/(n-1/12*1/(n+3/40*1/(n+2369/22680*1/n))))^n
 nemesCF4(n) : kern1(n)*(n/(n-1/12*1/(n+3/40*1/(n+2369/22680*1/(n+7828759/10745784*1/n)))))^n 

kern2 - approximations

 demoivre0(n) : N=n+1/2; kern2(N)
 demoivre1(n) : N=n+1/2; kern2(N)*(1-1/(24*N))
 demoivre2(n) : N=n+1/2; kern2(N)*(1-1/(24*N)+1/(1152*N^2))
 demoivre3(n) : N=n+1/2; kern2(N)*(1-1/(24*N)+1/(1152*N^2)+(1003/414720)/N^3)
 
 maclser0(n)  :          kern2(n+1/2)
 maclser1(n)  : N=2*n+1; kern2(n+1/2)*exp(-1/(12*N))
 maclser2(n)  : N=2*n+1; kern2(n+1/2)*exp(-1/(12*N)*(1-7/(30*N^2))) 
 maclser3(n)  : N=2*n+1; kern2(n+1/2)*exp(-1/(12*N)*(1-7/(30*N^2)*(1-62/(49*N^2)))) 
 
 wdsmith0(n)  : N=n+1/2; kern2(N) 
 wdsmith1(n)  : N=n+1/2; kern2(N)*exp((-1/24)/N) 
 wdsmith2(n)  : N=n+1/2; kern2(N)*exp((-1/24)/(N+(7/120)/N)) 
 wdsmith3(n)  : N=n+1/2; kern2(N)*exp((-1/24)/(N+(7/120)/(N+(1517/5880)/N))) 
 wdsmith4(n)  : N=n+1/2; kern2(N)*exp((-1/24)/(N+(7/120)/(N+(1517/5880)/(N+(164715/297332)/N))))  

 cantrell0(n) : N=n+1/2; kern2(N)
 cantrell1(n) : N=n+1/2; kern2(N)/(1+1/(24*N-1/2))
 cantrell2(n) : N=n+1/2; kern2(N)/(1+1/(24*N-1/2+1/((1440/2021)*N)))
 cantrell3(n) : N=n+1/2; kern2(N)/(1+1/(24*N-1/2+1/((1440/2021)*N+1/((686186088/125896643)*N))))
 cantrell4(n) : N=n+1/2; kern2(N)/(1+1/(24*N-1/2+1/((1440/2021)*N+1/((686186088/125896643)*N
                +1/((1521596612992267104/4596084813365743279)*N)))))

 lanczos0(n)  : N=n+1/2; kern2(N)
 lanczos1(n)  : N=n+1/2; kern2(N)*(1-(1/24)*(1/(n+1)))
 lanczos2(n)  : N=n+1/2; kern2(N)*(1-(1/24)*(1/(n+1))-(23/1152)*(1/((n+1)*(n+2))))
 lanczos3(n)  : N=n+1/2; kern2(N)*(1-(1/24)*(1/(n+1))-(23/1152)*(1/((n+1)*(n+2)))
                                    -(11237/414720)*(1/((n+1)*(n+2)*(n+3))))
   
 wehmeier0(n) : kern2(n)*sqrt(n)
 wehmeier1(n) : kern2(n)*sqrt(n+1/6)
 wehmeier2(n) : kern2(n)*sqrt(n+1/6+(1/72)/n)
 wehmeier3(n) : kern2(n)*sqrt(n+1/6+(1/72)/n-(31/6480)/n^2)
 wehmeier4(n) : kern2(n)*sqrt(n+1/6+(1/72)/n-(31/6480)/n^2-(139/155520)/n^3)

 gosper0(n)   : kern2(n)*sqrt(n)
 gosper1(n)   : kern2(n)*sqrt(n+1/6)
 gosper2(n)   : kern2(n)*sqrt(n+1/6)*(1+(1/144)/n^2)
 gosper3(n)   : kern2(n)*sqrt(n+1/6)*(1+(1/144)/n^2-(23/6480)/n^3)

 gospersmith0(n): N=n+1/2; NN=N^2; sqrt(2*Pi)*exp(-N)*(NN)^(N/2) 
 gospersmith1(n): N=n+1/2; NN=N^2; sqrt(2*Pi)*exp(-N)*(NN-(1/12))^(N/2) 
 gospersmith2(n): N=n+1/2; NN=N^2; sqrt(2*Pi)*exp(-N)*(NN+(1/12)*(-1+(1/(10*NN))))^(N/2)
 gospersmith3(n): N=n+1/2; NN=N^2; sqrt(2*Pi)*exp(-N)*(NN+(1/12)*(-1+(1/(10*NN))*(1-(185/(756*NN)))))^(N/2) 
 
 luschny0(n): N=n+1/2; NN=24*N^2; kern2(N) 
 luschny1(n): N=n+1/2; NN=24*N^2; kern2(N)*(1-1/NN)^N
 luschny2(n): N=n+1/2; NN=24*N^2; kern2(N)*(1-1/NN*(1-19/(10*NN)))^N
 luschny3(n): N=n+1/2; NN=24*N^2; kern2(N)*(1-1/NN*(1-1/(10*NN)*(19-2561/(21*NN))))^N
 luschny4(n): N=n+1/2; NN=24*N^2; kern2(N)*(1-1/NN*(1-1/(10*NN)*(19-1/(21*NN)*(2561-874831/(20*NN)))))^N 
 
 luschnyCF0(n): N=n+1/2; kern2(N)
 luschnyCF1(n): N=n+1/2; kern2(N)*(N/(N+1/24*1/N))^N
 luschnyCF2(n): N=n+1/2; kern2(N)*(N/(N+1/24*1/(N+3/80*1/N)))^N
 luschnyCF3(n): N=n+1/2; kern2(N)*(N/(N+1/24*1/(N+3/80*1/(N+18029/45360*1/N))))^N
 luschnyCF4(n): N=n+1/2; kern2(N)*(N/(N+1/24*1/(N+3/80*1/(N+18029/45360*1/(N+6272051/14869008*1/N)))))^N

miscellaneous approximations

 maclstir0(n) : (  2*maclser0(n)+    stirser0(n))/3
 maclstir1(n) : ( 32*maclser1(n)+ 31*stirser1(n))/63
 maclstir2(n) : ( 64*maclser2(n)+ 63*stirser2(n))/127
 maclstir3(n) : (128*maclser3(n)+127*stirser3(n))/255
 
 windschitl(n): N=n+1;   sqrt(2*Pi/N)*((N/e)*sqrt(N*sinh(1/N)))^N
 wdsmith*(n)  : N=n+1/2; sqrt(2*Pi)*((N/e)*sqrt(2*N*tanh(1/(2*N))))^N
 
 nemes*(n)    : N=n;     sqrt(2*Pi*N)*((N+1/(12*N-1/(10*N)))/e)^N
 nemesgam(n)  : N=n+1;   sqrt(2*Pi/N)*((N+1/(12*N-1/(10*N)))/e)^N
 luschny*(n)  : N=n+1/2; sqrt(2*Pi)*((N-1/(24*N+19/(10*N)))/e)^N           

How well do these formulas perform?

The following table displays the number of exact decimal digits (edd) of the formulas for some values of n. Exact decimal digits are defined as -log[10](abs(1-approximation/trueValue)). log[10] denotes the logarithm to the base 10. 

edd(n) = -log[10](abs(1 - approximation(n) / n!)).

In the following table the i-th entry (i=0,1,2,... from the left hand side to the right hand side) in a line starting with 'name' is the edd of formula namei(n). The '-' sign indicates that the approximation is smaller and the '+' sign (not displayed) indicates that the approximation is larger than the true value.
For example we see from the table that formula nemes1 gives the same number of exact decimal digits as the formula ramanujan2.

-----------------------------------------------------------------------
Formula          n!          exact decimal digits, edd(n)
-----------------------------------------------------------------------
                      
Stirling     00100!   -3.1   -6.5    8.6   11.7  -13.1
De Moivre    00100!    3.4   -7.1   -8.6   12.0   13.1
Gosper       00100!   -3.1   -6.2    8.5  -11.9 
Wehmeier     00100!   -3.1   -6.2    8.6   11.4  -13.1
Ramanujan    00100!   -3.1   -5.7   -9.2   11.0  -13.3
Nemes        00100!   -3.1          -9.2         -13.2    17.3   -21.1 
Luschny      00100!    3.4          -8.5          13.1   -17.2    21.1
Henrici      00100!   -3.1          -8.4         -13.2    17.2
GosperSonin  00100!    3.4          -8.4          13.0   -17.2   
StirSeries   00100!   -3.1           8.6         -13.1    17.3
MaclSeries   00100!    3.4          -8.6          13.1   -17.2
NemesCF      00100!    3.1           8.2          13.2    17.3    21.5
Stieltjes    00100!   -3.1           8.6         -13.2    17.5   -21.5
W.D.Smith    00100!    3.4          -8.6          13.2   -17.5    21.5
Cantrell     00100!    3.4          -8.6          13.2   -17.5    21.5
LuschnyCF    00100!    3.4           8.8          13.2    17.6    21.5
Windschitl   00100!                              -13.2 
W.D.Smith*   00100!                               13.2
Nemes*       00100!                              -13.2
NemesGamma   00100!                              -13.2
Luschny*     00100!                               13.2

Stirling     01000!   -4.1   -8.5   11.6   15.6  -18.1 
De Moivre    01000!    4.4   -9.1  -11.6   16.0   18.1
Gosper       01000!   -4.1   -8.2   11.4  -15.9 
Wehmeier     01000!   -4.1   -8.2   11.6   15.4  -18.1
Ramanujan    01000!   -4.1   -7.7  -12.2   15.0  -18.3
Nemes        01000!   -4.1         -12.2         -18.2    24.3   -30.1 
Luschny      01000!    4.4         -11.5          18.1   -24.2    30.1
Henrici      01000!   -4.1         -11.4         -18.2    24.2
GosperSonin  01000!    4.4         -11.4          18.0   -24.2  
StirSeries   01000!   -4.1          11.6         -18.1    24.2
MaclSeries   01000!    4.4         -11.6          18.1   -24.2
NemesCF      01000!    4.1          11.2          18.2    24.3    30.5
Stieltjes    01000!   -4.1          11.6         -18.2    24.4   -30.4
W.D.Smith    01000!    4.4         -11.6          18.2   -24.5    30.5
Cantrell     01000!    4.4         -11.6          18.2   -24.5    30.5
LuschnyCF    01000!    4.4          11.8          18.2    24.6    30.5 
Windschitl   01000!                              -18.2
W.D.Smith*   01000!                               18.2
Nemes*       01000!                              -18.2
NemesGamma   01000!                              -18.2
Luschny*     01000!                               18.2

Stirling     10000!   -5.1  -10.5   14.6   19.6  -23.1
De Moivre    10000!    5.4  -11.1  -14.6   20.0   23.1
Gosper       10000!   -5.1  -10.2   14.4  -19.9 
Wehmeier     10000!   -5.1  -10.2   14.6   19.3  -23.1
Ramanujan    10000!   -5.1   -9.7  -15.2   19.0  -23.3 
Nemes        10000!   -5.1         -15.2         -23.2    31.3   -39.1
Luschny      10000!    5.4         -14.5          23.1   -31.2    39.1 
Henrici      10000!   -5.1         -14.4         -23.2    31.2
GosperSonin  10000!    5.4         -14.4          23.0   -31.2   
StirSeries   10000!   -5.1          14.6         -23.1    31.2
MaclSeries   10000!    5.4         -14.6          23.1   -31.2
NemesCF      10000!    5.1          14.2          23.2    31.3    39.5
Stieltjes    10000!   -5.1          14.6         -23.2    31.4   -39.4
W.D.Smith    10000!    5.4         -14.6          23.2   -31.5    39.5
Cantrell     10000!    5.4         -14.6          23.2   -31.5    39.5
LuschnyCF    10000!    5.4          14.8          23.2    31.6    39.5
Windschitl   10000!                              -23.2 
W.D.Smith*   10000!                               23.2
Nemes*       10000!                              -23.2
NemesGamma   10000!                              -23.2
Luschny*     10000!                               23.2

Notes

** The reference for the Ramanujan formula is: S. Raghavan and S. S. Rangachari (eds.) "S. Ramanujan: The lost notebook and other unpublished papers", Springer, 1988, p. 339. Ramanujan's statement is as follows:

Gamma(x+1) = Sqrt(Pi)(x/e)^x (8x^3 + 4x^2 + x + theta(x)/30)^(1/6)
where theta(x) -> 1 as x -> oo and (3/10) < theta(x) < 1.

** Paul Abbott commented Ramanujan's statement on the Usenet (sci.math.num-analysis): "For

Sqrt(Pi)*(n/E)^n*(n*(4*n*(2*n+1)+1)+(1/30)*(1-(11/(8*n))*(1-(79/(154*n))
*(1+(3539/(4740*n))*(1-(9511/(7078*n))*(1+90459/(152176*n)))))))^(1/6)

one finds that

theta(x) = 1-11/(8*x)+79/(112*x^2)+3539/(6720*x^3)-9511/(13440*x^4)-30153/(71680*x^5)

Clearly theta(x) -> 1 for x -> Infinity. Also (3/10) < theta(x) < 1 for x >~ 1.3878. So this form does agree with Ramanujan's statement."

** Michael Hirschhorn [The Mathematical Gazette, Vol. 90, July 2006, 286-292] proved the following sharper bounds for Ramanujan's theta(x), valid for x > 6053/3987 (or x > 1.52).

1 - 11/(8*x) + 5/(8*x^2) < theta(x) < 1 - 11/(8*x) + 11/(8*x^2)

** The reference for Stieltjes' continued fraction formula is: M. Abramowitz, I. A. Stegun (eds.), Handbook of Mathematical Functions, p. 258, [6.1.48]. Note also: B. W. Char: "On Stieltjes' continued fraction for the gamma function", Mathematics of Computation 34, 150 (1980) 547-551.

** There are many Lanczos formulas for approximating n!. The form we use here is his equation (21) given in "A precision approximation of the gamma function", J. SIAM Numer. Anal., Ser. B, Vol. 1 (1964), pp. 86-96. Lanczos also devised other series (not included here) which might be more useful in practical computation. So he might not be fairly represented here! (Thanks to D. W. Cantrell for this remark.)

** The formulas of Warren D. Smith were taken from The Gamma function revisited, a typeset dated 29 Mar 2006.

** The formulas cantrell and wdsmith have an almost identical numerical performance.

** In our setup the approximation of Robert H. Windschitl is only a curiosity. Warren D. Smith's formula wdsmith*(n) provides a similar approximation based on Gamma(n+1/2). The two formulas wdsmith* and windschitl bracket the true value. (Note that our interpretation of the Windschitl formula differs from the interpretation used by W. D. Smith. However, our (Gamma-) interpretation seems to be more useful.)

zWindschitlz!W.D.Smith*
0.00.9996581.01.00429
0.50.886170.886230.88652
1.00.9999841.01.000057
1.51.3293331.3293401.329361
2.01.99999542.02.0000107

** I do not understand why the Windschitl formula is called 'a version suitable for calculators' on Wikipedia and other web-sides. The appearance of sinh (or tanh in the case of wdsmith*) make them look like stars of the 'Pimp My Formula' TV-show. Well, it is time to un-pimp these formulas and to introduce the cute nemesGamma(n) and luschny*(n) formulas, which are much simpler but equal powerful. (For the definitions see the paragraph Miscellaneous Approximations above.)

And there is an added value. Comparing windschitl(n) with nemesGamma(n) we find the following approximation:

sqrt(x sinh(1/x)) = 1 + 1/(12 x^2 - 1/10) + O(x^(-6))

In fact         | sqrt(x sinh(1/x)) - (1 + 1/(12 x^2 - 1/10)) | <  1 / (24192 x^6) .

Comparing wdsmith*(n) with luschny*(n) shows the approximation:

sqrt(x tanh(1/x)) = 1 - 1/(6 x^2 + 19/10) + O(x^(-6))

In fact         | sqrt(x tanh(1/x)) - (1 - 1/(6 x^2 + 19/10)) | <  1 / (54 x^6) .

These two approximations are noteworthy. It does not make sense to replace the simple right hand sides by the functions on the left hand side in the above approximations to the factorial function as this will not decrease the approximation error. It will only produce pimped formulas ;-)

** Some numerical methods for computing x! (the tricks of the trade) can be found in the Handbook of Mathematical Functions (6.7).

** Let us define the Noerlund scheme as

noerlund(z,h,m)
ln(sqrt(2*Pi))+(z+h-1/2)*ln(z)-z+sum((-1)^(j+1)*bernoulli(j+1,h)/((j+1)*j*z^j),j=1..m-1)

The Noerlund scheme [Vorlesungen über Differenzenrechnung, Berlin 1924, p.111] gives us a common framework to classify approximation formulas to x!. There are three basic types, which correspond to our more general abbreviations kern#(x) used in the table above.

KERN0(x) = exp(noerlund(x+1,0,0)) = sqrt(2Pi/Y)*(Y/e)^Y where Y=x+1
KERN1(x) = exp(noerlund(x,1,0)) = sqrt(2Pi*Y)*(Y/e)^Y where Y=x
KERN2(x) = exp(noerlund(x+1/2,1/2,0)) = sqrt(2Pi)*(Y/e)^Y where Y=x+1/2

Note that KERN1 has a problem when x=0. Therefore KERN0 is to be preferred to KERN1. KERN2 has the most simple form and might be called the Hermite-Sonin variant.

** Asymptotic approximation of the Bernoulli Numbers.

Combining the nemes* formula and the well known connection of the Bernoulli Numbers with the Riemann Zeta Function we find the following remarkable formula, valid for even n >= 4.

|B(n)| ~ 2 sqrt(2 Pi n) ((n + 1/(12 n - 1/(10 n)))/(2 Pi e))^n

For example this approximation gives
                      | B(100) | ~ 0.28382249570691.. 10^79
compared with
                      | B(100) | = 0.28382249570693.. 10^79.

We can write this formula also as an approximation to Zeta(1-n), valid for even n >= 4.

| Zeta(1-n) | ~ 2 sqrt(2 Pi / n)((n / (2 Pi e))((120 n^2 + 9)/(120 n^2 - 1)))^n   

Which approximation to choose?

The formulas given are mostly asymptotic formulas and this means they only give good approximations if x is large. However, for small values of x there is a simple trick to overcome this shortcoming at no great cost. Shift x in the direction -> +oo before evaluating and divide by the shifted amount afterwards. This is, of course, nothing else but a clever application of the functional equation of x!.

I am quite fond of the continued fraction approximation of T. J. Stieltjes because of its simplicity and the small constants involved. Note especially that this is a convergent approximation! So I built the above-mentioned trick in the following simple function based on the stieltjes3 formula and recommend its use if only moderate precision is needed.

StieltjesFactorial(x)
y = x+1; p = 1;
while y < 7 do p = p*y; y = y+1; od;
r = exp(y*log(y)-y + 1/(12*y+2/(5*y+53/(42*y))));
if x < 7 then r = r/p fi;
return r*sqrt(2*Pi / y) end;

This approximation guarantees 9 valid decimal digits. And you can expect about 7/2+3*log(x) valid significant decimal digits for x>=10. For programming a pocket calculator the following simplification of the fourth line is even better suited:
r = exp(y*(log(y)-1)+1/(2*(6*y+1/(5*(y+1/(4*y))))));
In the following plot the blue line represents the guaranteed 9 decimal digits, the green zigzag line shows the effect of the shift/divide-trick, and the red curve is the number of exact decimal digits of the 'pure' stieltjes3 approximation.

contfrac

How to display approximation values?

It is good practice to display only the valid digits of an approximation and not to leave the user more or less helplessly looking at long strings of digits figuring out how much of these digits he might assume as valid.

However, how this is done depends much on the implementation language. I give an example using pseudo-Maple-style, which in turn uses a formatting scheme which is very similar to the one used in the computer language 'C'.

PrintFactorial(x)
# Number of valid significant decimal digits for StieltjesFactorial.
l = floor(7/2+3*log(x));
# Put formatting specifications in the format string.
format = sprintf("%d! = %s%de\n",x,"%1.",l-1);
# Add some internal guarding digits and evaluate.
F = evalf(StieltjesFactorial(x),l+6);
printf(format, F) end;

Using this special print function to display the approximations to (2^i)!

Sequence( PrintFactorial(2^i), i = 0..12);

gives the following output, which shows only valid digits (the last digit might be rounded).

       1! = 1.00e+00
       2! = 2.0000e+00
       4! = 2.400000e+01
       8! = 4.03200000e+04
      16! = 2.0922789888e+13
      32! = 2.631308369337e+35
      64! = 1.26886932185884e+89
     128! = 3.85620482362580422e+215
     256! = 8.5781777534284265412e+506
     512! = 3.477289793132605363283e+1166
    1024! = 5.41852879605885728307692e+2639
    2048! = 1.6726919319100117051699525e+5894
    4096! = 3.642736389457041931565827470e+13019

A higher precision approximation

... and now we are going for the Big Pizza. The next approximation guarantees 16 valid decimal digits. And you can expect about 5/2+(13/2)*log(x) valid significant decimal digits for x >= 10 (see the next figure). I just give the pseudo-code because things are very similar to the things explained in the last two sections.

However, there is a small difference. This time we make explicit that we are using the logarithmic version of the continued fraction formula. This gives an additional layer of flexibility.

StieltjesLnFactorial(z)
a0 = 1/12; a1 = 1/30; a2 = 53/210; a3 = 195/371;
a4 = 22999/22737; a5 = 29944523/19733142;
a6 = 109535241009/48264275462;
Z = z+1; (1/2)*ln(2*Pi)+(Z-1/2)*ln(Z)-Z +
a0/(Z+a1/(Z+a2/(Z+a3/(Z+a4/(Z+a5/(Z+a6/Z)))))) end;

StieltjesFactorialHP(x)
y = x; p = 1;
while y < 8 do p = p*y; y = y+1; od;
r = exp(StieltjesLnFactorial(y));
if x < 8 then r = (r*x)/(p*y) fi;
r end;

PrintFactorialHP(x)
l = floor((5+13*log(x))/2);
format = sprintf("%d! = %s%de\n",x,"%1.",l-1);
F = evalf(StieltjesFactorialHP(x),l+6);
printf(format, F) end;

       1! = 1.00e+00
       2! = 2.000000e+00
       4! = 2.4000000000e+01
       8! = 4.032000000000000e+04
      16! = 2.0922789888000000000e+13
      32! = 2.631308369336935301672180e+35
      64! = 1.2688693218588416410343338934e+89
     128! = 3.856204823625804217356770659234637e+215
     256! = 8.5781777534284265411908227168123262516e+506
     512! = 3.477289793132605363283045917545604711992251e+1166
    1024! = 5.4185287960588572830769219446838547380015539636e+2639
    2048! = 1.672691931910011705169952468793676234018507002356737e+5894
    4096! = 3.6427363894570419315658274703116469205712449235098554300e+13019

contfrac

Conclusions and Recommendations

Note: This paragraph was written before I discovered the 'luschnyCF' formulas and is not up-to-date.

The Stirling formula is a very useful formula when we have to do some Big-O (complexity-) analysis. But if we are only interested in the numerical evaluation of the factorial function then there is no reason to use the Stirling approximation or some of its many asymptotic variants. Because there exist convergent approximations which are

In our judgement there are three outstanding formulas which we declare the winners of our little contest.

Clearly the continued fraction of W. D. Smith is a variant of Stieltjes' formula. And the coefficients of this formula are slightly larger than those of the Stieltjes formula. Another runner-up is Cantrell's formula, which is numerically on par with Smith's formula but has even larger rational constants (which does not really matter if we are using floating point arithmetic with fixed precision). Note that we looked only at the real range x > 1. If considered throughout the complex half-plane Re(z) > 1 there might be some special strength or weakness in the formulas which we have not noticed.

Summa summarum we highly recommend Stieltjes' formula whenever a numerical approximation of the factorial function is required.

Update-history

=> A000207 at OEIS.

Recently Rainer Rosenthal drew my attention to the number of planar 2-trees, sequence A000207 at OEIS. The sequence can be computed as (Maple):
A000108 := n -> (2*n)! / (n!*(n+1)!);
A000207 := n -> A000108(n)/(2*n+4)+A000108(floor(n/2))*(3-modp(n,2))/4 +`if`(modp(n,3)=1,A000108(floor((n-1)/3))/3,0);

I noticed that the quotient A000207(n+1) / A000207(n) has a remarkable regular asymptotic expansion:
QuotAsymptotic := n -> 4 - (10/n)*(1-(3/n)*((1-(3/n)*((1-(3/n)*((1-(3/n) *((1-(3/n)*((1-(3/n)*((1-(3/n)))))))))))))).

=> Update Jan 11, 2007: The computation of Stieltjes' continued fraction.

After calculating his famous continued fraction for the Gamma function Stieltjes remarked: "Le calcul est trés pénible ... la loi de ces nombres paraît extrêmement compliqué". I looked at the state of the art and  wrote a summary. See the link list below.

=> Update Jan 9, 2007: Two new continued fraction approximations added.

My latest additions are the formulas luschnyCT and nemesCT. A first comparison shows that the luschnyCT formula performs slightly better than Stieltjes' formula (or the W.D.Smith or Cantrell formula).

=> Update Jan 4, 2007: Three simple but powerful formulas added.

The formulas nemes*, nemesGamma and luschny* are new. They are much simpler than the windschitl or wdsmith* formulas but equal powerful.

=> Update Dec 28, 2006: The Luschny formulas added.

The new Luschny formulas added following Sonin's 'half-shift' idea and similar to the Nemes approach.

=> Update Dec 14, 2006: The Gosper-Smith formulas added.

Gosper's z! ~ sqrt((2*z+1/3)*Pi)*(z/e)^z recasted by W. D. Smith following Sonin's 'half-shift' idea.

=> Update Dec 13, 2006: Warren D. Smith's formulas added.

The continued fraction formulas of W. D. Smith are based on the Hermite-Sonin discussion: Sur les polynômes d'Bernoulli, Extrait d'une correspondance entre M. Sonin et M. Hermite. J. für Math. 116 (1896), 133-156.

=> Update Nov 18, 2006: The Continued Fraction Formula corrected

Gergö Nemes spotted an error in stieltjes3. Thanks, Gergö! With this correction, the author hopes that the formulas are now error-free. 

=> Update Nov 12, 2006: The Nemes Formula announced

Gergö Nemes, a student from Hungary, sent me his formula. Thank you Gergö for sharing your findings with us!

nemes

=> Update Nov 9, 2006: The Wehmeier Formula rediscovered

weh

In expanded normal form:

weh

First I thought that I had discovered a new family of formulas. However, a closer examination showed that I had rediscovered the Wehmeier formula while I was contemplating the Ramanujan formula. Nevertheless, I left the L-formula in the table because I think this alternative way to look at the Wehmeier formula throw some light on the structure of the Ramanujan formula.

=> Update Aug, 2006: S. Ramanujan's Formula

ramanujan

In expanded normal form:

ramanujan

Links

* David W. Cantrell's announcement "A new convergent expansion for the gamma function"
  OEIS-A119422
* Knud Thomsen's formula for small positive values
* Stefan Wehmeier's announcement of his approximation.
* G. R. Pugh's thesis "An analysis of the Lanczos gamma approximation"
* Hugo Pfoertner's Fortran implementation of Cantrell's expansion.
* 'Calculators and the Gamma Function' about the origin of the Windschitl-formula.
* New The computation of Stieltjes' continued fraction.
* The winner is ...

previous Back to the Homepage of Factorial Algorithms.             Valid XHTML 1.1

~ FIN ~