The following program is a javascript program which calculates pi. You can enter the
number of digits you want in the box, and choose whether to separate the digits with a
space every 5 digits, or whether to add the count at the end of each line, or not. Try the
program to see how this works.
Even though this is a rather slow program, it calculates 1000 digits of pi in about 13
seconds (13.028 seconds on one occasion), on a slow computer. The time taken to calculate
a given number of digits does not merely double on doubling the number of digits, but
increases about fourfold. So we would expect 2000 digits to take four times as long.
Internet Explorer gives a message saying the script seems to be running for a long time.
Press "No" to continue, or "Yes" to abort. It reports 57.993 seconds
for 2000 digits. To calculate to 5000 places, the program took 324.266 seconds, with
Internet Explorer complaining twice.
The program doesn't round the final digit, but reports 5 more digits than requested,
some of these five may be wrong (the last few digits calculated with the Machin formula
will nearly always be wrong). The digits requrested will, however, be correct. You can
check digits using the pi
search.
Even though this program is slow, compared with the history of pi, it is utterly
remarkable compared with the history of pi.
In 1666 Sir Isaac Newton calculated pi to 15 places. He used a formula of his own
devising. This formula was extremely slow to converge, and I suspect that Newton may have
spent months, or even years, rather than hours, calculating 15 places.
In 1706, John Machin proposed a formula that converged very quickly.
Using Machin's formula, in 1873, William Shanks, after many years of labour, published
his calculation of pi to 707 places.
A Frenchman called Dagbert, memorised pi to 707 places, indicating that he had used
Shanks work. It was quite popular for some mathematics students to learn pi to many
digits, using Shanks work. However, it was only in the 1930s that suspicians began to
arise that Shanks had made an error. In fact, he had made an error in the 528th place, so
the remaining 180 digits were wrong. Professor Aitken, a mathematician from New Zealand,
recorded his chagrin when he discovered that learning 707 decimal places of pi had been in
vain.
The above, while amusing, probably isn't true, even though it is told in many places
and by many famous people, see
Carey Bloodworth's interesting article, also available on site here.
In 1949, the computer ENIAC took 70 hours to compute the value of pi to 2037 decimal
places.
In recent years, pi has been computed to 1.24 trillion places.
The heavily commented code for the pi program follows.
<html>
<head>
<title>Pi Machin</title>
<script language="javascript" type="text/javascript">
<!--//
mess="";
//10^11 seems to be the maximum
//too high a figure for the base introduces errors
Base=Math.pow(10,11);
//num digits in each array item
cellSize=Math.floor(Math.log(Base)/Math.LN10);
//below is not used in this script
a=Number.MAX_VALUE;
MaxDiv=Math.floor(Math.sqrt(a));
function makeArray (n, aX, Integer) {
var
i=0;
for
(i=1; i<n; i++)
aX[i] = null;
aX[0] = Integer;
}
function isEmpty (aX) {
var empty=true
for
(i=0; i<aX.length; i++)
if
(aX[i])
{
empty= false;
break;
}
return
empty;
}
//junior school math
function Add (n, aX,aY) {
carry=0
for
(i=n-1; i>=0; i--) {
aX[i] += Number(aY[i])+Number(carry);
if
(aX[i]<Base)
carry = 0;
else {
carry = 1;
aX[i] =Number(aX[i])- Number(Base);
}
}
}
//subtract
function Sub (n, aX,aY) {
for
(i=n-1; i>=0; i--) {
aX[i] -= aY[i];
if
(aX[i]<0) {
if
(i>0) {
aX[i] += Base;
aX[i-1]--;
}
}
}
}
//multiply big number by
"small" number
function Mul (n, aX, iMult) {
carry=0;
for
(i=n-1; i>=0; i--) {
prod = (aX[i])*iMult;
prod += carry;
if
(prod>=Base) {
carry = Math.floor(prod/Base);
prod -= (carry*Base);
}
else
carry = 0;
aX[i] = prod;
}
}
//divide big number by
"small" number
function Div (n, aX, iDiv,aY) {
carry=0;
for
(i=0; i<n; i++) {
//add any previous carry
currVal = Number(aX[i])+Number(carry*Base);
//divide
theDiv =Math.floor(currVal/iDiv);
//find next carry
carry = currVal-theDiv*iDiv;
//put the result of division in the
current slot
aY[i] = theDiv;
}
}
//compute arctan
function arctan (iAng, n, aX) {
iAng_squared=iAng*iAng;
k=3; //k is the coefficient in the
series 2n-1, 3,5..
sign=0;
makeArray (n, aX, 0); //aX is
aArctan
makeArray (n, aAngle, 1);
Div (n, aAngle, iAng, aAngle); //aAngle
= 1/iAng, eg 1/5
Add (n, aX, aAngle); // aX = aAngle
or long angle
while
(!isEmpty(aAngle)) {
Div (n, aAngle, iAng_squared, aAngle); //aAngle=aAngle/iAng_squared, iAng_squared is iAng*iAng
//mess+="iAng="+iAng+";
aAngle="+aAngle+"<br>";
Div (n, aAngle, k, aDivK); /* aDivK
= aAngle/k */
if
(sign)
Add (n, aX, aDivK); /* aX = aX+aDivK
*/
else
Sub (n, aX, aDivK); /* aX = aX-aDivK */
k+=2;
sign = 1-sign;
}
mess+="aArctan="+aArctan+"<br>";
}
// Calculate pi
function calcPI (numDec) {
var ans="";
t1=new
Date();
numDec=Number(numDec)+5;
iAng=new
Array(10);
coeff=new Array(10);
arrayLength=Math.ceil(1+numDec/cellSize);
aPI = new Array(arrayLength);
aArctan = new Array(arrayLength);
aAngle=new Array(arrayLength);
aDivK=new Array(arrayLength);
//Pi/4 = 4*arctan(1/5)-arctan(1/239)
//coeff is an array of the coefficients
//the last item is 0!
coeff[0] = 4;
coeff[1] = -1;
coeff[2] = 0;
//iAng holds the angles, 5 for 1/5,
etc
iAng[0] = 5;
iAng[1] = 239;
iAng[2] = 0;
makeArray (arrayLength, aPI, 0);
//Machin: Pi/4 =
4*arctan(1/5)-arctan(1/239)
makeArray(arrayLength,aAngle,0);
makeArray(arrayLength,aDivK,0);
for (var i=0; coeff[i]!=0; i++) {
arctan(iAng[i], arrayLength, aArctan);
//multiply by coefficients of arctan
Mul (arrayLength, aArctan, Math.abs(coeff[i]));
//mess+="mi="+coeff[i]+"<br>";
if
(coeff[i]>0)
Add (arrayLength, aPI, aArctan);
else
Sub (arrayLength, aPI, aArctan);
//mess+="api="+aPI+"<br>";
}
//we have calculated pi/4, so need to finally multiply
Mul (arrayLength, aPI, 4);
//we have now calculated PI, and
need to format the answer
//to print it out
sPI="";
tempPI="";
//put the figures in the array into
the string tempPI
for (i=0;i<aPI.length;i++)
{
aPI[i]=String(aPI[i]);
//ensure there are enough digits in each cell
//if not, pad with leading zeros
if
(aPI[i].length<cellSize&&i!=0)
{
while
(aPI[i].length<cellSize)
aPI[i]="0"+aPI[i];
}
tempPI+=aPI[i];
}
//now put the characters into the string sPI
for (i=0;i<=numDec;i++)
{
//put the 3 on a different line, and add a decimal point
if (i==0)
sPI+=tempPI.charAt(i)+".<br>";
else
{
//split the long line up into manageable rows
if (document.getElementById("cbCount").checked)
addcount=" ("+(i)+")";
else
addcount="";
if (document.getElementById("cbSpace").checked)
thespace=" ";
else
thespace="";
if ((i)%50==0&&i!=0)
sPI+=tempPI.charAt(i)+addcount+"<br>";
else
if (i%5==0)
sPI+=tempPI.charAt(i)+thespace;
else
sPI+=tempPI.charAt(i);
}//i not zero
}
//now put the print-out together
//print our pi
ans+=("PI ("+numDec+")="+sPI+"<br>");
//Window's calculator Pi (for confirmation);
ans+=("Win
PI=<br>3.1415926535897932384626433832795<br>");
t2=new Date();
timeTaken=(t2.getTime()-t1.getTime())/1000;
ans+="It took: "+timeTaken+"
seconds";
//document.write(mess);
var
myDiv=document.getElementById("d1");
myDiv.innerHTML=ans;
}
//-->
</script>
</head>
<body bgcolor="white">
<h1>Pi Machin</h1>
<form name="" id="" method="post" action="" enctype="text/plain" onsubmit="calcPI(this.t1.value);return false;">
Number of Digits:<br>
<input type="text" name="t1" id="t1" value="100" size="25" maxlength="25"><br>
Add Count:
<input type="checkbox" name="cbCount" id="cbCount" value="" checked="checked"><br>
Add Spaces:
<input type="checkbox" name="cbSpace" id="cbSpace" value="" checked="checked"><br>
<input type="button" value="Calculate
Pi" onclick="calcPI(this.form.t1.value)">
</form>
<div id="d1">Answer appears here</div>
</body>
</html>