下面的是学习写程序的时候写的计算PI到一百万位的程序;用的展开式,算法复杂度long(n*n)
有更快的计算PI的公式,比如二次收敛的几何级数公式;
Borwein四次收敛迭代式(很多专业算PI的程序使用了的这两个公式):
初值:
a0=6-4*2^0.5
y0=2^0.5-1
重复计算:
y(n+1)=[1-(1-y^4)^0.25]/[1+(1-y^4)^0.25];
y=y(n+1);
a(n+1)=a*(1+y)^4-2^(2*n+3)*y*(1+y+y*y);
最后计算:
PI=1/a;
{用级数计算PI的delphi源代码,2001-6}
unit UnitUnitPI;
interface
uses Windows,SysUtils,Forms;
//函数接口 (计算位数;返回字符串结果)
procedure AccountPI(MLength:integer;var strPI:string);
//------------------------------------------------------
// 把数组形结果转化为字符串结果
procedure GetstrPI(MLength:integer;nl:integer;var PiA :array of integer;var strPI:string);
implementation
// 利用展开式:
// PI/4=7/10*(1+2/3*(1/50)^1+2/3*4/5*(1/50)^2+...) +
// 7584/100000*(1+2/3*(144/100000)^1+2/3*4/5*(144/100000)^2+...)
procedure AccountPI(MLength:integer;var strPI:string);
var n:integer;
i:integer;
j:integer;
k:integer;
PiA1:array of integer;
PiA:array of integer;
ExitOk:integer;
nl:integer;
E10 :integer;
begin
nl:=3;
E10:=1;
for j:=1 to nl do E10:=E10*10;
n := abs(mLength) div nl + 3;
i := 0 ;
setlength( PiA,n+2);
setlength( PiA1,n+3);
PiA1[1] := 2800;
PiA[1] := -200;
ExitOK:=1;
while true do
begin
i := i + 2;
k := i + 1;
FOR j := ExitOK TO n do PiA1[j] := PiA1[j] * i;
FOR j := ExitOK TO n do
begin
PiA1[j + 1] := (PiA1[j] MOD 50) * E10 + PiA1[j + 1];
PiA1[j] := PiA1[j] div 50;
end;
FOR j := ExitOK TO n do
begin
PiA1[j + 1] := (PiA1[j] MOD k) * E10 + PiA1[j + 1];
PiA1[j] := PiA1[j] div k;
PiA[j] := PiA[j] + PiA1[j];
end;
if i mod 500=0 then
begin
application.ProcessMessages;
FOR j := n downTO 1 do
begin
PiA[j - 1] := PiA[j] div E10 + PiA[j - 1];
PiA[j] := PiA[j] MOD E10;
end;
end;
PiA1[n + 1] := 0;
ExitOK:=1;
FOR k := 1 TO n do
begin
IF not (PiA1[k]=0) THEN
begin
ExitOK:=k;
break;
end;
end;
if ExitOK=n then break;
end
/////----------
i := 0;
ExitOK:=1;
PiA1[1] := 303;
PiA1[2] := 360;
PiA[1] := PiA[1] + 303;
PiA[2] := PiA[2] + 360;
while true do
begin
i := i + 2;
k := i + 1;
FOR j := ExitOK TO n do PiA1[j] := PiA1[j] * i * 9;
FOR j := ExitOK TO n do
begin
PiA1[j + 1] := PiA1[j + 1] + (PiA1[j] MOD 6250) * E10 ;
PiA1[j] := PiA1[j] div 6250 ;
end;
FOR j := ExitOK TO n do
begin
PiA1[j + 1] :=PiA1[j + 1] + (PiA1[j] MOD k) * E10;
PiA1[j] := PiA1[j] div k;
PiA[j] := PiA[j] + PiA1[j];
end;
if i mod 500=0 then
begin
application.ProcessMessages;
FOR j := n downTO 1 do
begin
PiA[j - 1] := PiA[j] div E10 + PiA[j - 1];
PiA[j] := PiA[j] MOD E10;
end;
end;
PiA1[n + 1] := 0 ;
ExitOK:=1;
FOR k := 1 TO n do
begin
IF not (PiA1[k]=0) THEN
begin
ExitOK:=k;
break;
end;
end;
if ExitOK=n then break;
end;
//-----------
FOR j := n downTO 1 do
begin
PiA[j - 1] := PiA[j] div E10 + PiA[j - 1];
PiA[j] := PiA[j] MOD E10;
end;
PiA1[n + 1] := 0 ;
GetstrPI(MLength,nl,PiA,strPI);
setlength( PiA,0);
setlength( PiA1,0);
end;
//-----------------------------------------------
procedure GetstrPI(MLength:integer;nl:integer;var PiA :array of integer;var strPI:string);
var strT :string;
j :integer;
i :integer;
tempK :integer;
n :integer;
begin
n := abs(mLength) div nl + 3;
strPI:= '3.';
FOR j := 1 TO n do
begin
strT:= inttostr(PiA[j]);
for i:=1 to ( nl-length(strT) ) do strT:='0'+strT;
IF j = n - 1 THEN
begin
tempk :=mLength MOD nl;
strT := copy(strT,1,tempk) + '<>' + copy(strT,tempK+1,nl-tempk);//多三位
END;
strPI:=strPI+strT;
if j mod 500=0 then application.ProcessMessages;
end;
END;
end.
///
别人的C代码
#include <stdlib.h>
#include <stdio.h>
long 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
*a,f=d%--g,d/=g--,--b;d*=b)
}