fb:porticula NoPaste
FAST PI CALCULATOR (1999)
Uploader: | Volta |
Datum/Zeit: | 13.10.2008 16:56:52 |
#Lang "qb"
'===========================================================================
' Subject: FAST PI CALCULATOR V4.8 Date: 02-28-99 (23:41)
' Author: Jason Stratos Papadopoulos Code: QB, QBasic, PDS
' Origin: jasonp@Glue.umd.edu Packet: ALGOR.ABC
'===========================================================================
DECLARE SUB atan239 (denom&)
DECLARE SUB atan5 (denom&)
DECLARE SUB PrintOut (words%)
'Program to calculate pi, version 4.8
'A major rewrite of version 4.2, this uses only two arrays instead of
'three, and includes a host of speedups based on a similar C program.
'A sampler: all the carries are reserved until the end, the divide and
'add routines are combined, two terms are added at a time, and the number
'of function calls is minimized. It's a big change for a small gain, since
'the compiled version requires 28.6 seconds for 5000 digits on my 486 66MHz
'computer, a 10% gain over version 4.2; like before, it's capable of about
'150,000 digits of pi.
'
'This program has come a long way from version 1.0; thanks are due to
'Larry Shultis, Randall Williams, Bob Farrington and Adrian Umpleby.
'One final note for speed freaks: this program will run about 6 times faster
'if written in C using an optimizing compiler. Likewise, if you can figure
'out a way to do integer division and use both the quotient and remainder,
'this program can easily be sped up by 25%. -jasonp@isr.umd.edu
DEFINT A-Z
Dim SHARED words, firstword, lastword
CLS
INPUT "how many digits"; digits&
words = digits& \ 4 + 3
DIM SHARED sum&(words + 1), term(words + 1)
start! = TIMER
'---------------16*atan(1/5)
denom& = 3: firstword = 1: lastword = 2
sum&(1) = 3: term(1) = 3: sum&(2) = 2000: term(2) = 2000
DO UNTIL firstword >= words
CALL atan5(denom&)
denom& = denom& + 2
LOOP
'------------ -4*atan(1/239)
denom& = 3: firstword = 2: remainder& = 4
FOR x = 2 TO words
dividend& = remainder& * 10000 'crunch out 1st term
term(x) = dividend& \ 239&
remainder& = dividend& - term(x) * 239&
sum&(x) = sum&(x) - term(x)
NEXT x
DO UNTIL firstword >= words
CALL atan239(denom&)
denom& = denom& + 4
LOOP
FOR x = words TO 2 STEP -1 '-------finish up
IF sum&(x) < 0 THEN 'release carries
quotient& = sum&(x) \ 10000 'and borrows
sum&(x) = sum&(x) - (quotient& - 1) * 10000
sum&(x - 1) = sum&(x - 1) + quotient& - 1
END IF
IF sum&(x) >= 10000 THEN
quotient& = sum&(x) \ 10000
sum&(x) = sum&(x) - quotient& * 10000
sum&(x - 1) = sum&(x - 1) + quotient&
END IF
NEXT x
CALL PrintOut(words)
PRINT "computation time: "; TIMER - start!; " seconds"
sleep
END
'------------------------------------------------------------------
SUB atan239 (denom&)
'SHARED words, firstword
remainder1& = term(firstword) 'first divide implicitly
remainder2& = 0: remainder3& = 0: remainder4& = 0
denom2& = denom& + 2: firstword = firstword + 1
FOR x = firstword TO words
temp& = term(x)
dividend& = remainder1& * 10000 + temp&
temp& = dividend& \ 57121
remainder1& = dividend& - temp& * 57121
dividend& = remainder2& * 10000 + temp&
temp2& = dividend& \ denom&
remainder2& = dividend& - temp2& * denom&
sum&(x) = sum&(x) + temp2&
dividend& = remainder3& * 10000 + temp&
temp& = dividend& \ 57121
remainder3& = dividend& - temp& * 57121
dividend& = remainder4& * 10000 + temp&
temp2& = dividend& \ denom2&
remainder4& = dividend& - temp2& * denom2&
sum&(x) = sum&(x) - temp2&
term(x) = temp&
NEXT x
firstword = firstword + 1
IF term(firstword) = 0 THEN firstword = firstword + 1
END SUB
'-------------------------------------------------------------------
SUB atan5 (denom&)
'SHARED words, firstword, lastword
FOR x = firstword TO lastword + 1
temp& = term(x)
dividend& = remainder1& * 10000 + temp&
temp& = dividend& \ 25
remainder1& = dividend& - temp& * 25&
term(x) = temp&
dividend& = remainder2& * 10000 + temp&
temp& = dividend& \ denom&
remainder2& = dividend& - temp& * denom&
sum&(x) = sum&(x) - temp&
NEXT x
FOR x = lastword + 2 TO words
dividend& = remainder2& * 10000
temp& = dividend& \ denom&
remainder2& = dividend& - temp& * denom&
sum&(x) = sum&(x) - temp&
NEXT x
IF term(lastword + 1) > 0 AND lastword < words THEN lastword = lastword + 1
IF term(firstword) = 0 THEN firstword = firstword + 1
denom& = denom& + 2
remainder1& = 0: remainder2& = 0
FOR x = firstword TO lastword + 1
temp& = term(x)
dividend& = remainder1& * 10000 + temp&
temp& = dividend& \ 25
remainder1& = dividend& - temp& * 25&
term(x) = temp&
dividend& = remainder2& * 10000 + temp&
temp& = dividend& \ denom&
remainder2& = dividend& - temp& * denom&
sum&(x) = sum&(x) + temp&
NEXT x
FOR x = lastword + 2 TO words
dividend& = remainder2& * 10000
temp& = dividend& \ denom&
remainder2& = dividend& - temp& * denom&
sum&(x) = sum&(x) + temp&
NEXT x
IF term(lastword + 1) > 0 AND lastword < words THEN lastword = lastword + 1
IF term(firstword) = 0 THEN firstword = firstword + 1
END SUB
'------------------------------------------------------------------
SUB PrintOut (words)
PRINT "pi = 3."
FOR i = 1 TO words \ 3
PRINT " ";
PRINT RIGHT$("0000" + LTRIM$(STR$(sum&(3 * (i - 1) + 2))), 4);
PRINT RIGHT$("0000" + LTRIM$(STR$(sum&(3 * (i - 1) + 3))), 4);
PRINT RIGHT$("0000" + LTRIM$(STR$(sum&(3 * (i - 1) + 4))), 4);
IF i MOD 5 = 0 THEN PRINT " :"; 12 * i
NEXT i
PRINT " ";
FOR i = 3 * (words \ 3) + 2 TO digits
PRINT RIGHT$("0000" + LTRIM$(STR$(sum&(i))), 4);
NEXT i
PRINT : PRINT
END SUB