Pi: Difference between revisions

12,268 bytes added ,  4 months ago
m
m (syntax highlighting fixup automation)
m (→‎{{header|Wren}}: Minor tidy)
(12 intermediate revisions by 7 users not shown)
Line 524:
=={{header|BASIC}}==
 
==={{header|Applesoft BASIC}}===
<syntaxhighlight lang="basic">10 REM ADOPTED FROM COMMODORE BASIC
20 N = 100: REM N MAY BE INCREASED, BUT WILL SLOW EXECUTION
Line 700:
3.14159265358979323846264338327950288419716939937510582097494459230781...
</pre>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
{{works with|Applesoft BASIC}}
{{works with|MSX_BASIC}}
{{works with|QBasic}}
{{trans|Applesoft BASIC}}
<syntaxhighlight lang="qbasic">100 REM adopted from Applesoft BASIC
110 n = 100 : rem n may be increased, but will slow execution
120 ln = int(10*n/3)+16
130 nd = 1
140 dim a(ln)
150 n9 = 0
160 pd = 0 : rem First pre-digit is a 0
170 rem
180 for j = 1 to ln
190 a(j-1) = 2 : rem Start wirh 2S
200 next j
210 rem
220 for j = 1 to n
230 q = 0
240 for i = ln to 1 step -1 : rem Work backwards
250 x = 10*a(i-1)+q*i
260 a(i-1) = x-(2*i-1)*int(x/(2*i-1)) : rem X - Int ( X / Y) * Y
270 q = int(x/(2*i-1))
280 next i
290 a(0) = q-10*int(q/10)
300 q = int(q/10)
310 if q = 9 then n9 = n9+1 : goto 510
320 if q <> 10 then goto 440
330 rem Q == 10
340 d = pd+1 : gosub 560
350 if n9 <= 0 then goto 400
360 for k = 1 to n9
370 d = 0 : gosub 560
380 next k
390 rem End If
400 pd = 0
410 n9 = 0
420 goto 510
430 rem Q <> 10
440 d = pd : gosub 560
450 pd = q
460 if n9 = 0 then goto 510
470 for k = 1 to n9
480 d = 9 : gosub 560
490 next k
500 n9 = 0
510 next j
520 print str$(pd)
530 end
540 rem
550 rem Output digits
560 if nd = 0 then print str$(d); : return
570 if d = 0 then return
580 print str$(d);".";
590 nd = 0
600 return</syntaxhighlight>
 
==={{header|Commodore BASIC}}===
Line 746 ⟶ 804:
410 N9 = 0
450 NEXT J
460 PRINT RIGHT$(STR$(PD),1)
470 END
480 REM
490 REM OUTPUT DIGITS
500 IF ND=0 THEN PRINT RIGHT$(STR$(D),1);: RETURN
510 IF D=0 THEN RETURN
520 PRINT RIGHT$(STR$(D),1);".";
530 ND = 0
550 RETURN
</syntaxhighlight>
 
==={{header|Integer BasicGW-BASIC}}===
{{works with|PC-BASIC|any}}
The [[#Chipmunk_Basic|Chipmunk Basic]] solution works without any changes.
 
==={{header|Integer Basic}}===
Integer version was derived from the Pascal_spigot without any optimisation. It is more than 33% faster than the Applesoft version since it runs natively with integers.
 
Line 808 ⟶ 869:
</syntaxhighlight>
 
==={{header|Osborne 1 MBASICIS-BASIC}}===
<syntaxhighlight lang="is-basic">100 PROGRAM "PI.bas"
110 LET N=100 ! Nuber of digits
120 LET LN=INT(10*N/3)+16
130 DIM A(LN)
140 LET PD,N9=0:LET ND=1
150 FOR J=1 TO LN
160 LET A(J-1)=2
170 NEXT
180 FOR J=1 TO N
190 LET Q=0
200 FOR I=LN TO 1 STEP-1
210 LET X=10*A(I-1)+Q*I
220 LET A(I-1)=X-(2*I-1)*INT(X/(2*I-1))
230 LET Q=INT(X/(2*I-1))
240 NEXT
250 LET A(0)=Q-10*INT(Q/10)
260 LET Q=INT(Q/10)
270 SELECT CASE Q
280 CASE 9
290 LET N9=N9+1
300 CASE 10
310 LET D=PD+1:CALL WRITE
320 IF N9>0 THEN
330 FOR K=1 TO N9
340 LET D=0:CALL WRITE
350 NEXT
360 END IF
370 LET PD,N9=0
380 CASE ELSE
390 LET D=PD:CALL WRITE
400 LET PD=Q
410 IF N9<>0 THEN
420 FOR K=1 TO N9
430 LET D=9:CALL WRITE
440 NEXT
450 LET N9=0
460 END IF
470 END SELECT
480 NEXT
490 PRINT STR$(PD)(1)
500 END
510 DEF WRITE
520 IF ND=0 THEN
530 PRINT STR$(D)(1);
540 ELSE IF D<>0 THEN
550 PRINT STR$(D)(1);".";
560 LET ND=0
570 END IF
580 END DEF</syntaxhighlight>
 
==={{header|MSX Basic}}===
The [[#Chipmunk_Basic|Chipmunk Basic]] solution works without any changes.
 
==={{header|Osborne 1 MBASIC}}===
Osborne 1 program is slightly different to allow it to keep the numbers all on the main screen rather than scrolling off to the right...
 
Line 3,506 ⟶ 3,620:
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745...
</pre>
 
=={{header|Lambdatalk}}==
1) We can build a lambdatalk function using the lib_BN javascript library.
 
<syntaxhighlight lang="scheme">
{require lib_BN}
 
{def genpi
{def genpi.loop
{lambda {:n :pi :q :r :t :i :z}
{if {> :z :n}
then :pi
else {let { {:n :n} {:pi :pi} {:q :q} {:r :r} {:t :t} {:i :i} {:z :z}
{:digit {BN./ {BN.+ {BN.* {BN.- {BN.* :i 27} 12} :q}
{BN.* :r 5} }
{BN.* :t 5} } }
{:u {BN.* {BN.+ {BN.* :i 3} 1}
{BN.* 3 {BN.+ {BN.* :i 3} 2} } } }
} {genpi.loop :n
{BN.+ :pi :digit}
{BN.* {BN.* :q 1}
{BN.* :i {BN.- {BN.* :i 2} 1} }}
{BN.* {BN.* :u 1}
{BN.+ {BN.* :q {BN.- {BN.* :i 5} 2} }
{BN.- :r {BN.* :t :digit} }}}
{BN.* :t :u}
{BN.+ :i 1}
{+ :z 1}} }}}}
{lambda {:n}
{genpi.loop :n # 1 180 60 2 0} }}
-> genpi
 
We can generate π with 72 digits in about 500ms.
 
{BN.DEC 72}
-> 72 digits
{genpi 60}
-> 3.141592653589793238462643383279502884197169399375105820974944592307816406
</syntaxhighlight>
 
To go further the best is to build a javascript primitive using the script special form.
 
<syntaxhighlight lang="scheme">
{script
LAMBDATALK.DICT["spigot"] = function() {
function generateDigitsOfPi(max) {
var pi = "";
var z = 0;
var q = 1n;
var r = 180n;
var t = 60n;
var i = 2n;
while (z < max) {
var digit = ((i * 27n - 12n) * q + r * 5n) / (t * 5n);
pi += digit;
var u = (i * 3n + 1n) * 3n * (i * 3n + 2n);
r = u * 10n * (q * (i * 5n - 2n) + (r - t * digit));
q = q * 10n * i * (i * 2n - 1n);
i = i + 1n;
t = t * u;
z++;
}
return pi
}
var args = arguments[0].trim();
return generateDigitsOfPi( args );
};
}
 
We can generate 1000 digits of π in about 70ms
 
3.{W.rest {spigot 100}}
-> 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198
 
</syntaxhighlight>
 
=={{header|Lasso}}==
Line 3,743 ⟶ 3,932:
WriteString[$Output, RealDigits[Pi, 10, 1, i][[1, 1]]]; Pause[.05]];</syntaxhighlight>
 
=={{header|MATLAB}} / {{header|Octave}}==
Requires the Variable Precision Integer (vpi) Toolbox
Matlab and Octave use double precision numbers per default, and pi is a builtin constant value. Arbitrary precision is only implemented in some additional toolboxes (e.g. symbolic toolbox).
<syntaxhighlight lang="matlab">pi</syntaxhighlight>
function pi_str = piSpigot(N)
% Return N digits of pi using Gibbons's first spigot algorithm.
% If N is omitted, the digits are printed ad infinitum.
% Uses the expansion
% pi = sum_{i=0} (i!)^2 2^{i+1} /(2i+1)!
% = 2 + 1/3 * ( 2 + 2/5 * (2 + 3/7 * ( 2 + 4/9 * ( ..... )))))
% = (2 + 1/3 *)(2 + 2/5 *)(2 + 3/7 *)...
% where the terms in the last expression represent Linear Fractional
% Transforms (LFTs).
%
% Requires the Variable Precision Integer (vpi) Toolbox
%
% Reference:
% "Unbounded Spigot Algorithms for the Digits of Pi" by J. Gibbons, 2004
% American Mathematical Monthly, vol. 113.
if nargin < 1
N = Inf;
lineLength = 50;
else
pi_str = repmat(' ',1,N);
end
 
q = vpi(1);
r = vpi(0);
t = vpi(1);
k = 1; % If printing more than 3E15 digits, use k = vpi(1);
 
i = 1;
first_digit = true;
while i <= N
threeQplusR = 3*q + r;
n = double(threeQplusR / t);
if q+threeQplusR < (n+1)*t
d = num2str(n);
if isinf(N)
fprintf(1,'%s', d);
if first_digit
fprintf(1,'.');
first_digit = false;
i = i+1;
end
if i == lineLength
fprintf(1,'\n');
i = 0;
end
else
pi_str(i) = d;
end
q = 10*q;
r = 10*(r-n*t);
i = i + 1;
else
t = (2*k+1)*t;
r = (4*k+2)*q + (2*k+1)*r;
q = k*q;
k = k + 1;
end
end
end
</syntaxhighlight>
<pre>
>> pipiSpigot
3.141592653589793238462643383279502884197169399375
ans = 3.1416
10582097494459230781640628620899862803482534211706
> printf('%.60f\n',pi)
79821480865132823066470938446095505822317253594081
3.141592653589793115997963468544185161590576171875000000000000>> format long
28481117450284102701938521105559644622948954930381
96442881097566593344612847564823378678316527120190
91456485669234603486104543266482133936072602491412
</pre>
<pre>
Unfortunately this is not the correct value!
3.14159265358979323846264338327950288419716939937510582
=================??????????????????????????????????????</pre>
 
=={{header|MiniScript}}==
Calling for 60 digit output does not produce 60 digits of precision. Once the sixteen digit precision of double precision is reached, the subsequent digits are determined by the workings of the binary to decimal conversion. The long decimal string is the exact decimal value of the binary representation of pi, which binary value is itself not exact because pi cannot be represented in a finite number of digits, be they decimal, binary or any other integer base...
Calculate pi using the Rabinowitz-Wagon algorithm
<syntaxhighlight lang="miniscript">digits = input("Enter number of digits to calculate after decimal point: ").val
// I've seen variations of this "precision" calculation from
// 10 * digits
// to
// floor(10 * digits / 3) + 16
// A larger value provides a more precise calculation but also
// takes longer to run. Based on my testing, this calculation
// below for precision produces accurate output for inputs
// from 1 to 4000 - haven't tried larger than this.
precision = floor(10 * digits / 3) + 4
A = [2] * precision
nines = 0
predigit = 0
cnt = 0
while cnt <= digits
carry = 0
for i in range(precision - 1, 1, -1)
temp = 10 * A[i] + carry * i
A[i] = temp % (2 * i - 1)
carry = floor(temp/(2 * i - 1))
end for
A[1] = carry % 10
carry = floor(carry / 10)
current = carry
if current == 9 then
nines += 1
else if current == 10 then
print (predigit+1), ""
cnt += 1
if nines > 0 then
print "9" * nines, ""
cnt += nines
end if
predigit = 0
nines = 0
else
// the first digit produced is always a zero
// don't need to see that
if cnt != 0 then print predigit, ""
cnt += 1
predigit = current
if nines > 0 then
print "9" * nines, ""
cnt += nines
end if
nines = 0
end if
if cnt == 2 then print ".", ""
end while
print str(predigit) * (cnt < digits + 2)</syntaxhighlight>
 
{{out}}
<pre>
Enter number of digits to calculate after decimal point: 1000
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903690113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051329005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710199031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066139019278766111959092164201989
</pre>
 
=={{header|Nanoquery}}==
Line 5,061 ⟶ 5,366:
exit /*stick a fork in it, we're all done. */
halt: say; say 'PI_SPIT2 halted via use of Ctrl-Break.'; exit</syntaxhighlight> <br><br>
 
=={{header|RPL}}==
It is not easy to print character by character with RPL. Something could be done with the <code>DISP</code> instruction, but it would require to manage the cursor position - and anyway the emulator does not emulate <code>DISP</code> !
===Rabinowitz & Wagon algorithm===
{{trans|BBC Basic}}
There is probably a way to translate the BBC BASIC approach into something that uses only the stack, but it has been preferred here to use 'global' variables with the names used by the BBC BASIC program - except for <code>e</code>, which represents the Euler constant in RPL.
{{works with|Halcyon Calc|4.2.7}}
≪ '''IF''' 1 FS?C '''THEN''' "π = " 'output' STO '''END'''
SWAP →STR '''WHILE''' DUP2 SIZE > '''REPEAT''' "0" SWAP + '''END'''
output SWAP + 'output' STO DROP
'PRINT' STO
≪ → m
≪ 1 SF {} 1 m '''START''' #20d + '''NEXT'''
#0d 'ee' STO #2d 'l' STO
m 14 '''FOR''' c
#0 'd' STO c 2 * 1 - R→B 'a' STO
c 1 '''FOR''' p
DUP p GET 100 * d p * + 'd' STO
p d a / LAST ROT * - PUT
'd' a STO/ 'a' 2 STO-
-1 '''STEP'''
'''IF''' d #99d ==
'''THEN''' ee 100 * d + 'ee' STO #2h 'l' STO+
'''ELSE'''
'''IF''' c m ==
'''THEN'''
d 100 / B→R 10 / 0 PRINT
d 100 / LAST ROT * - 'ee' STO
'''ELSE'''
ee d 100 / + B→R l B→R PRINT
d 100 / LAST ROT * - 'ee' STO #2h 'l' STO
'''END'''
'''END'''
-7 '''STEP'''
DROP output
≫ ≫
'M→π' STO
 
200 M→π
{{out}}
<pre>
1: "π = 3.14159265358979323846264338327950288419716939937510582"
</pre>
=== Faster Rabinowitz & Wagon implementation===
{{trans|Fortran}}
This much faster version favors the stack to local variables.
≪ SWAP →STR
'''IF''' 1 FS?C '''THEN''' "." + '''ELSE WHILE''' DUP2 SIZE > '''REPEAT''' "0" SWAP + '''END''' output SWAP + '''END'''
'output' STO DROP
'WRITE' STO
≪ DUP 50 * 3 / IP → n m
≪ 1 SF 0 {} m + 2 CON 0
1 n '''START'''
DROP 0
m 1 '''FOR''' p
p * OVER p GET 100000 * +
p DUP + 1 - MOD LAST / IP
ROT p 4 ROLL PUT SWAP
-1 '''STEP'''
DUP 100000 MOD LAST / IP
5 ROLL + 5 WRITE
ROT ROT
'''NEXT'''
3 DROPN output
≫ ≫
'N→π' STO
 
100 N→π
{{out}}
<pre>
"3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011" </pre>
 
=={{header|Ruby}}==
Line 6,009 ⟶ 6,389:
{{trans|Kotlin}}
{{libheader|Wren-big}}
<syntaxhighlight lang="ecmascriptwren">import "./big" for BigInt
import "io" for Stdout
 
9,485

edits