Ramanujan and Salamin-Brent Methods for π

Math 242 Modern Computational Mathematics

Ramanujan's Method

Here is Ramanujan's sum:
(1/π)=((2(Sqrt[2]))/9801)  (∑_(k=0)^∞)(((4k)!(1103+26390k))/((((k!))^4)(396^(4k))))

Complete the following module to add up the first n terms of Ramanujan’s sum and return an approximation of π:

ramanujan[n_]:=Module[
{sum=0},
Do[
sum+=(((4k)!(1103+26390k))/((k!)^4*396^(4k))),
{k,0,n}];
(*return value*)
sum*=2((Sqrt[2])/9801);
1/sum
]

Demonstrate that your module returns exact values that are close to π.

ramanujan[3]

Table[ramanujan[n],{n,1,3}]

Shorthand syntax for Table is /@, like this:

ramanujan/@Range[3]

How many correct digits of π are produced by each term of Ramanujan’s sum?

nMax=20;
piValuesRamanujan=ramanujan/@Range[20]

N[ramanujan[3],50]
N[Pi,50]

$MaxExtraPrecision=1000;
accuracyRamanujan=N[-Log[10,Abs[Pi-piValuesRamanujan]],6]

ListPlot[accuracyRamanujan,AxesLabel->{"n","correct digits"}]

TableForm[Transpose[{Range[nMax],accuracyRamanujan}],TableHeadings->{None,{"terms","correct digits"}}]

compute differences in successive accuracy values:

Table[accuracyRamanujan[[n]]-accuracyRamanujan[[n-1]],{n,2,nMax}]

Ramanujan's method produces about eight correct digits for each term that we add.

Salamin-Brent Algorithm

Implement a module that computes approximations of π using the Salamin-Brent method (Algorithm 1.20 on page 31 in the text). Your module should accept one input parameter: an integer that specifies how many iterations of the algorithm to compute. Make a table showing how the number of correct digits of π increases with the number of terms that you add up. Answer the question: What is the relationship between the number of iterations and the number of correct digits of π?

A note about subscripts

You can define subscript variables, but this is not recommended:

(Subscript[a, 1])=3

?a

DownValues[Subscript]

Don' t use subscripts, instead use indexed variables:

a[1]=3

a[2]=7

?a

Salamin - Brent Algorithm

Now for the Salamin-Brent algorithm:

salaminBrent[numIterations_]:=Module[
{a,b,s,p},

(* initialize values *)
a[0]=1;
b[0]=1/Sqrt[2];
s[0]=1/2;

(* main loop *)
Do[
a[k]=(a[k-1]+b[k-1])/2;
b[k]=Sqrt[a[k-1]*b[k-1]];
s[k]=s[k-1]-2^k*(a[k]^2-b[k]^2);
p[k]=2a[k]^2/s[k],
{k,1,numIterations}];

(* return value *) 
p[numIterations]
]

Compute the first two iterations:

salaminBrent/@Range[2]

Determine the accuracy:

piValuesSalaminBrent=salaminBrent/@Range[8];

accuracySalaminBrent=N[-Log[10,Abs[Pi-piValuesSalaminBrent]],5]

It looks like the number of accurate digits approximately doubles with each iteration!