Contributor: DAVID ADAMSON (* PROGRAM PI5.PAS By David Adamson October 23, 1994 This it the third version of a program for computing Pi up to 2150 places. The first version was written in Turbo Pascal 3. The second was also in Turbo Pascal, but with all the math procedures converted to inline for maximum program executing speed. This version is rewritten to allow compilation with Turbo Pascal 5 and up. The inline code was scrapped for version 3. The sacrifice in speed is not a problem, because it improvement in today's computers overshadows the processing efficiency loss. Here are my results using a 33MHz 386. Pi v2 Pi v3 100 places = 0.1 sec 100 places = 0.3 sec 1000 places = 11 sec 1000 places = 32 sec 2135 places = 48 sec 2135 places = 150 sec ---------------------------------------------------------------------- THIS IS THE ORIGINAL HEADER: PROGRAM PI1.PAS TANDY 2000 BY CINO HILLIARD APRIL 6 , 1986 ( AN IMPROVED VERSION OF MY ORIGIONAL PI.PAS IN THE DL) THIS PROGRAM COMPUTES THE DIGITS OF PI USING THE ARCTANGENT FORMULA ( TERM 1 ) ( TERM 2 ) (1) PI/4 = 4 ARCTAN 1/5 - ARCTAN 1/239 IN CONJUNCTION WITH THE GREGORY SERIES N (2) ARCTAN X = SUM [ (-1)^M*(2M + 1)^-1*X^(2M+1) ] (APPROXIMATELY) M=0 SUBSTITUTING INTO (1) AND (2) THE FIRST FEW VALUES OF N, REARRANGING, SIMPLYIFING, AND NESTING WE HAVE, PI= 3.2 + 1/25[-3.2/3 + 1/25[3.2/5 + 1/25[-3.2/7 + ...].].] ( TERM 1 ) -1/239[4 +1/239^2[-4/3 +1/239^2[4/5 +1/239^2[-4/7 +...].].] ( TERM 2 ) USING THE LONG DIVISION ALGORITHM AND SOME TRICKS I DISCOVERED, THIS ( NESTED ) INFINITE SERIES CAN BE USED TO CALCULATE PI TO A LARGE NUMBER OF DECIMAL PLACES IN A REASONABLE AMOUNT OF TIME. A TIME FUNCTION IS INCLUDED TO SHOW HOW SLOW THINGS GET WHEN N IS LARGE. IMPROVEMENTS CAN BE MADE BY INCREASING THE NUMBER OF DIGITS EACH ARRAY ELEMENT HOLDS AND BY CHANGING THE DATA TYPE FROM INTEGER TO REAL FOR SELECTED VARIABLES. OF COURSE THE ADDED NUMBER OF DIGITS THESE CHANGES PRODUCE WILL COST MUCH MUCH MORE TIME. AH INDEED, 'TIS NO FREE LUNCH! HOWEVER, SINCE TERM 1 AND TERM 2 ARE COMPUTED SEPERATELY AND SINCE THE ARRAYS ARE STEP BY STEP UPDATED, THE PROGRAM DOES LEND ITSELF TO PARALLEL OR NON VON ( WHAT A COINCIDENCE - SEE BELOW ) PROCESSING. FOR EXAMPLE, LET COMPUTER 1 PERFORM TERM 1 AND COMPUTER 2 PERFORM TERM 2. MOREOVER, LET SEVERAL COMPUTERS SHARE IN THE CALCULATION OF EACH OF THE INDIVIDUAL TERMS. HOWEVER, TO KEEP EACH COMPUTER EQUALLY BUSY, A LOGARITHMIC TYPE OF ADJUSTMENT MUST BE MADE TO DECIDE ON THE NUMBER OF TERMS TO BE ASSIGNED TO EACH COMPUTER. SINCE THE HIGHER POWER TERMS REQUIRE MUCH LONGER TO COMPUTE, THE COMPUTERS ASSIGNED TO HIGHER POWERS MUST BE GIVEN FEWER TERMS TO DO. A LITTLE HISTORY ---------------- IN AUGUST, 1949, PROFESSOR JOHN VON NEUMANN USED FORMULAS (1) AND (2) TO CALCULATE PI TO 2035 DECIMAL PLACES ON THE ENIAC COMPUTER. THE EFFORT WAS MADE TO DETERMINE IF THE DIGITS CONFORMED TO SOME TYPE OF PATTERN OR IF THEY WERE RANDOMLY DISTRIBUTED. THE CALCULATION WAS COMPLETED OVER THE LABOR DAY WEEKEND WITH THE COMBINED EFFORTS OF FOUR ENIAC STAFF MEMBERS WORKING IN EIGHT-HOUR SHIFTS TO ENSURE CONTINUOUS OPERATION OF THE ENIAC. THE CALCULATION (INCLUDING CARD HANDLING TIME) TOOK APPROXIMATELY 70 HOUR. THE CONCLUSION WAS AS SUSPECTED - THE DIGITS APPEARED TO BE RANDOM! SOME YEARS AGO I REQUESTED INFORMATION ON PI FROM THE ENCYCLOPEDIA BRITANNICA RESEARCH SERVICE. I RECEIVED A REPORT GIVING THE ABOVE HISTORICAL ACCOUNT PLUS A LISTING OF THE 2035 DIGITS. A LITTLE COMMENT ---------------- USING MY T2K, PI1.PAS COMPUTES PI TO 2035 PLACES IN 15 MIN 31.97 SEC. GEE WHIZ! WHAT EARTHLY USE CAN BE MADE OF THIS? I PLAN TO MAKE DESIGNS AND COLOR PATTERNS USING THE DIGIT VALUES AS THE BASIS. MAYBE SOMETHING LIKE FRACTALS WOULD BE A GOOD START. THIS IS WHY COMPUTATION AND SPEED ARE IMPORTANT AS I DO NOT WISH (NOR TRUST) TO KEY IN ENTRIES FROM A PUBLISHED LIST. CINO HILLIARD [72756,672] --------------------------------------------------------------------------- MODIFICATIONS MADE FOR VERSION 2: ADDED INLINE CODE TO IMPROVE THE SPEED. USING THE ORIGINAL SOURCE ON MY TANDY-1000 ( WITH A V20 CPU ) , COMPUTING PI TO 2035 PLACES RAN IN 39 MIN 44.92 SEC.. AFTER ADDING THE INLINE CODE IT RAN IN 10 MIN 25.16 SEC.. ADDED A TIME FUNCTION FROM 'TECH JOURNAL FEB 85'. THIS USES A MSDOS INTERUPT, SO IT SHOULD RUN ON ANY MSDOS COMPATIBLE COMPUTER. CHUCK WHITE [75006,3677] *) PROGRAM PI5; Uses DOS, CRT; Type TimeString = string[12]; VAR K,I,I2,J,M,N,Q,V,R,D,Z : INTEGER; A,P,T : ARRAY[0..5000] OF integer; TI,T2 : STRING[20]; function Time: TimeString; var Hour, Minute, Second, Sec100 : word; Hr, Min, Sec, Hun : string[2]; begin gettime(Hour, Minute, Second, Sec100); str(Hour:2, Hr); str(Minute:2, Min); str(Second:2, Sec); str(Sec100:2, Hun); if Hr[1] = ' ' then Hr[1] := '0'; if Min[1] = ' ' then Min[1] := '0'; if Sec[1] = ' ' then Sec[1] := '0'; if Hun[1] = ' ' then Hun[1] := '0'; time := Hr+ ':'+ Min+ ':'+ Sec+ '.'+ Hun end; PROCEDURE DIV32IA; { DIVIDE 3.2 BY I AND STORE IN ARRAY A } BEGIN Q:=3 DIV I; R:=3 MOD I; A[0]:=Q; V:=R*10+2; Q:=V DIV I; R:=V MOD I; A[1]:=Q; FOR J:=2 TO M DO BEGIN V:=R*10; Q:=V DIV I; R:=V MOD I; A[J]:=Q; END; END; PROCEDURE DIVA(D:INTEGER); { DIVIDE A BY SPECIFIED INTEGER FROM } BEGIN { PROCEDURE COMPUTE; } R:=0; FOR J:=0 TO M DO BEGIN V:= R*10+A[J]; Q:= V DIV D; R:= V MOD D; A[J]:=Q; END; END; PROCEDURE DIV4IA; { DIVIDE 4 BY I AND STORE IN A } BEGIN Q:=4 DIV I; R:=4 MOD I; A[0]:=Q; FOR J:=1 TO M DO BEGIN V:= R*10; Q:= V DIV I; R:= V MOD I; A[J]:=Q; END; END; PROCEDURE DIV32IP; { DIVIDE 3.2 BY I AND STORE IN P } BEGIN Q:=3 DIV I; R:=3 MOD I; P[0]:=Q; V:=R*10+2; Q:=V DIV I; R:=V MOD I; P[1]:=Q; FOR J:=2 TO M DO BEGIN V:= R*10; Q:= V DIV I; R:= V MOD I; P[J]:=Q; END; END; PROCEDURE DIV4IP; { DIVIDE 4 BY I AND STORE IN P } BEGIN Q:=4 DIV I; R:=4 MOD I; P[0]:=Q; FOR J:=1 TO M DO BEGIN V:= R*10; Q:= V DIV I; R:= V MOD I; P[J]:=Q; END; END; PROCEDURE SUBA; { SUBTRACT A FROM P AND STORE IN A } BEGIN FOR J:=0 TO M DO A[J]:=P[J]-A[J]; END; PROCEDURE SUB32A; { SUBTRACT A FROM 3.2 AND STORE IN T } BEGIN T[0]:=3; T[1]:=1; FOR J:=2 TO M DO T[J]:=9-A[J]; END; PROCEDURE SUB4A; { SUBTRACT A FROM 4 AND STORE IN A } BEGIN A[0]:=3; FOR J:=1 TO M DO A[J]:=9-A[J]; END; PROCEDURE SUBT; { SUBTRACT TERM2 FROM TERM 1 AND STORE IN A } BEGIN FOR J:=M DOWNTO 1 DO BEGIN A[J]:=T[J]-A[J]; WHILE A[J]<0 DO BEGIN A[J]:=A[J]+10; { ADJUST FOR NEGATIVE } A[J-1]:=A[J-1]+1; END; WHILE A[J]>9 DO { ADJUST A FOR EXCESS CARRY } BEGIN A[J]:=A[J]-10; A[J-1]:=A[J-1]-1; END; END; END; PROCEDURE COMPUTE; { COMPUTE THE NESTED SERIES FOR I2 ITERATIONS } BEGIN I:=I2; { COMPUTE TERM 1 TO I2 PLACES } DIV32IA; DIVA(25); WHILE I>3 DO BEGIN I:=I-2; DIV32IP; SUBA; DIVA(25); END; SUB32A; I:=I2; { COMPUTE TERM 2 TO I2 PLACES } DIV4IA; DIVA(239); DIVA(239); WHILE I>3 DO BEGIN I:=I-2; DIV4IP; SUBA; DIVA(239); DIVA(239); END; SUB4A; DIVA(239); SUBT; { SUBTRACT TERM 2 FROM TERM 1 AND STORE IN A } T2:=TIME; { SET END OF COMPUTATION TIME } END; PROCEDURE STORE; { SAVE PI AND TIME TO DISK FILES } VAR BUFF : FILE OF INTEGER; F : TEXT; BEGIN ASSIGN(BUFF,'PI.DTA'); ASSIGN(F,'TIME.DTA'); REWRITE(BUFF); REWRITE(F); FOR J:=0 TO M-2 DO WRITE(BUFF,A[J]); WRITE(F,TI); {Note, does not produce an ascii readable} WRITE(F,T2); {output. It is for use by PILIST - code } {for PILIST is at the end after PI5} CLOSE(BUFF); CLOSE(F); END; procedure compute_time; var h1,h2,m1,m2,s1,s2,hun1,hun2,code,x: integer; s,temp: string[11]; begin val(copy(ti,1,2),h1,code); val(copy(t2,1,2),h2,code); val(copy(ti,4,2),m1,code); val(copy(t2,4,2),m2,code); val(copy(ti,7,2),s1,code); val(copy(t2,7,2),s2,code); val(copy(ti,10,2),hun1,code); val(copy(t2,10,2),hun2,code); if hun2