Approximating Pi with Continued Fractions

Initializing live version
Download to Desktop

Requires a Wolfram Notebook System

Interact on desktop, mobile and cloud with the free Wolfram Player or other Wolfram Language products.

Continued fractions provide a very effective toolset for approximating functions. Usually the continued fraction expansion of a function approximates the function better than its Taylor or Fourier series. This Demonstration compares the quality of two approximations for . One is a continued fraction approximation derived from one for the Gamma function and based on that, the other is a continued fraction expansion the author has developed as a canonical even contraction.

Contributed by: Andreas Lauschke (March 2011)
Open content licensed under CC BY-NC-SA


Snapshots


Details

The number of terms used in the continued fraction expansion is , and is a parameter (natural number). Larger values of increase the quality of the approximation.

The approximation using the noncontracted continued fraction is

.

The approximation using the contracted continued fraction is

Additional Information:

The algorithm uses the backward recurrence method to compute the continued fraction expansion. This method has been shown to be extremely stable for most continued fraction expansions, which is extremely important on numerical platforms that incur truncation/round-off error due to the limitations of machine precision. It can be shown that the backward recurrence method ("from tail to head") is vastly more stable (even self-correcting) than the forward recurrence method ("from head to tail") for two important classes of continued fractions: the Stieltjes continued fractions (which include the C-fractions) and those that fulfill the parabolic convergence region theorem. Several function classes with known Stieltjes continued fraction expansions include: exponential integrals, incomplete gamma functions, logarithms of gamma functions, the error function, ratios of successive Bessel functions of the first kind, Euler's hypergeometric function, as well as various elementary transcendental functions. The forward recurrence method (which solves a second-order linear difference equation), however, can be computationally more efficient due to the carry-over of results from one step to the next, which is a property the backward recurrence method does not possess.

Although the terms in the canonical contraction are more complex than the ones in the original noncontracted continued fraction expansion, the speed gain on traditional numerical platforms (Java, .Net, C) is substantial. The following uses 10,000 uniformly distributed random numbers between 3 and 20 for and between 0 and 5 for and outputs the computation time. As the design of the canonical contraction requires only Floor[n/2]-1 steps to produce the same number when steps are used in the original noncontracted continued fraction expansion, steps are used for the function "noncontracted" to ensure both methods attain the same accuracy. To minimize any possible inaccuracies in the Java time measurement due to cycle lapses every computation is carried out 1000 times.

import java.util.Random; public class piapprox { final private static int factorial(final int k) { int kk=1; for (int i = 1; i k; i++) { kk = kk * i; } return kk; } final private static int power(final int k) { int kk=1; for (int i = 1; i k; i++) { kk = kk * 2; } return kk; } final private static double noncontracted(final int steps, final int k) { double res=0; for (int m = steps; m > 0; m--) { res = (1 + m*(-4 + 4*m))/ (8*k+2 + res); } int numerator =factorial(k)*factorial(k); int denominator=factorial(2*k); return (double) numerator*numerator/denominator/denominator*power(4*k)* 4/(4*k+1+res); } final private static double contracted(final int steps, final int k) { double res=0; for (int m = steps-1; m > -1; m--) { res = (-225 + m*(-960 + m*(-1504 + (-1024 - 256*m)*m)))/ ((78 + k*(32 + 64*k) + m*(96 + 32*m)) + res); } int numerator =factorial(k)*factorial(k); int denominator=factorial(2*k); return (double) numerator*numerator/denominator/denominator*power(4*k)* 4/(4*k+1+(2 + 8*k)/(13 + k* (32 + 64*k)+res)); } final public static void main(String[] args) { Random generator = new Random(); long t1, t2; long t3=0; long t4=0; double ratio; int n,k; for (int c = 0; c < 10000; c++) { n = 3+generator.nextInt(18); k = generator.nextInt(5); t1 = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { noncontracted(2*n+2,k); } t2 = System.currentTimeMillis(); t3= t3+t2-t1; t1 = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { contracted(n,k); } t2 = System.currentTimeMillis(); t4= t4+t2-t1; } ratio=(double)t3/t4; System.out.println("Method: non-contracted, Milliseconds: " + t3); System.out.println("Method: contracted, Milliseconds: " + t4+", Ratio: "+ratio); } }

One can clearly see that the contracted continued fraction approximation outperforms by 30 to 60% in every case.

The backward recurrence method of the continued fraction expansion is also more stable than its conversion to a Padé approximation, even when several forms of the efficient HornerForm of the numerator and denominator polynomials are used.



Feedback (field required)
Email (field required) Name
Occupation Organization
Note: Your message & contact information may be shared with the author of any specific Demonstration for which you give feedback.
Send