]> Pi - Computing Pi in C

Computing Pi in C

Dik T. Winter wrote a 160-byte C program to compute the first 800 digits of pi. We analyze his code here. The original code

int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5;
for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,
f[b]=d%--g,d/=g--,--b;d*=b);}

can be rewritten as:

#include <stdio.h>

int main() {
    int r[2800 + 1];
    int i, k;
    int b, d;
    int c = 0;

    for (i = 0; i < 2800; i++) {
        r[i] = 2000;
    }

    for (k = 2800; k > 0; k -= 14) {
        d = 0;

        i = k;
        for (;;) {
            d += r[i] * 10000;
            b = 2 * i - 1;

            r[i] = d % b;
            d /= b;
            i--;
            if (i == 0) break;
            d *= i;
        }
        printf("%.4d", c + d / 10000);
        c = d % 10000;
    }

    return 0;
}

Then we see that during the first iteration of the k loop, the code is essentially computing the digits of

2 (1 +1 3 (1 +2 5 (1 +...(1 +2799 2 2799 +1 (1 +0 ))...)))

By Beeler et al. 1972, Item 120, this is an approximation of π.

We note each term in the approximation gives an additional bit of precision (see above link) thus 14 terms give 4 decimal digits of precision each time (since 2 14 >10 4 ). This is why 2800 =14 ×200 terms are used.

To get a better idea of what the program does, let us write

a 0 b 0 =1 ,a 1 b 1 =1 3 ,a 2 b 2 =2 5 ,...

where each a i,b i are coprime positive integers.

Set n=2799 . Then our goal is to compute the digits of

P=2 (1 +a 1 b 1 (1 +a 2 b 2 (1 +...(1 +a nb n(1 ))...)

Let x=2 10 7 . In the first iteration, we compute

P 0 =x+a 1 1 b 1 (x+...a n1 1 b n1 (x+a n1 b nx)...)

Let x=q nb n+r n and q ib i+r i=x+q i+1 b i+1 for i<n where the q i,r i are positive integers. Then P 0 =q 0 , and we have

10 7 P=q 0 +r 0 +a 1 b 1 (r 1 +a 2 b 2 (r 2 +...(r n1 +a nb n(r n))...).

The program then prints out q 0 mod10 4 , which should be the first four digits of an eight-digit number.

The first four digits are subtracted away. Then on the next iteration, we roughly compute 10 4 times the error term

r 0 +a 1 b 1 (r 1 +a 2 b 2 (r 2 +...(r n1 +a nb n(r n))...)

add any possible carry to the unprinted digits from the last iteration, and print the first four digits. This process is repeated until 200 digits are being printed. At each step, we can forget about 14 terms because from the above bounds we know they cannot possibly affect any other digits.

However there is one thing I don't understand. Why is it guaranteed only four digits will be printed each time? For example if we add a carry to 9999 then it will take five digits. In fact, 9999 appears in the first 200 digits, but fortunately there is no carry immediately after that.