The digits of Pi are printed 20 per line, by successively recomputing pi with higher precision. The computation is not accurate to the entire scale (for example, scale = 4; 4*a(1) prints 3.1412 instead of the expected 3.1415), so the program includes two excess digits in the scale. Fixed number of guarding digits will eventually fail because Pi can contain arbitrarily long sequence of consecutive 9s (or consecutive 0s), though for this task it might not matter in practice. The program proceeds more and more slowly but exploits bc's unlimited precision arithmetic.

The program uses three features of GNU bc: long variable names, # comments (for the #! line), and the print command (for zero padding).

Using Machin's formula. The "continuous printing" part is silly: the algorithm really calls for a preset number of digits, so the program repeatedly calculates Pi digits with increasing length and chop off leading digits already displayed. But it's still faster than the unbounded Spigot method by an order of magnitude, at least for the first 100k digits.

This is a transcription of the example Fortran programme written by S. Rabinowitz in 1991. It works in base 100000 and the key step is the initialisation of all elements of VECT to 2, done by the DATA statement. The source style is nearly F77 only, except for the output format code of I5.5 which means I5 output but with all leading spaces made zero so that 66 comes out as "00066", not " 66". Similarly, the label-style DO-loops are used rather than DO ... END DO but I have adjusted the indentation, and supplied the initial comment thus enlarging the source by one line to fifteen lines, not the fourteen in the references. As was routine, variables are not declared if the implicit declarations suffice, the absence of the PARAMETER statement means multiple appearance of magic numbers such as 3350 and 201, and commentary is absent...

The output is accumulated in BUFFER then written in one go at the end, but it could be written as successive values as each is calculated without much extra nitpickery: instead of BUFFER(N) = MORE + K for example just WRITE (*,"(I5.5)") MORE + K and no need for array BUFFER.

This is an alternate version using an unbounded spigot. Higher precision is accomplished by using the Fortran Multiple Precision
Library, FMLIB (http://myweb.lmu.edu/dmsmith/fmlib.html), provided by Dr. David M. Smith ([email protected]), Mathematics Professor (Emeritus) at Loyola Marymount University. We use the default precision which is about 50 significant digits.

The focus in this section is on the Gibbons spigot algorithm as it
is relatively simple and therefore provides a gentle introduction to
how such algorithms can be implemented in jq.

Since the Gibbons algorithm quickly fails in the absence of support for large integers, we shall assume BigInt support, such as provided by BigInt.jq.

The jq program presented here closely follows the Groovy and Python
examples on this page. The spigot generator is named "next", and is
driven by an annotation function, "decorate"; thus the main program
is just "S0 | decorate(next)" where S0 is the initial state. One
advantage of this approach is that the generator's state is exposed,
thus making it easy to restart the stream at any point.

The annotation defined here results in a triple for each digit of pi:
[index, digit, space], where "space" is the the sum of the lengths of
the strings in the six-dimensional state vector, [q, r, t, k, n, l].
The output shows that the space requirements of the Gibbons
spigot grow very slightly more than linearly.

# The Gibbons spigot, in the mold of the [[#Groovy]] and ython]] programs shown on this page. # The "bigint" functionsneeded are: long_minus long_add long_multiply long_div

Julia comes with built-in support for computing π in arbitrary precision (using the GNU MPFR library). This implementation computes π at precisions that are repeatedly doubled as more digits are needed, printing one digit at a time and never terminating (until it runs out of memory) as specified:

Unfortunately this is not the correct value!
3.14159265358979323846264338327950288419716939937510582
=================??????????????????????????????????????

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...

Perl being what it is, there are many ways to do this with many variations. With a fixed number of digits and the Math::BigInt::GMP library installed, the [[Arithmetic-geometric mean/Calculate Pi code will be much faster than any of these methods other than some of the modules. If Math::GMP is installed, then replacing "use bigint" with "use Math::GMP qw/:constant/" in either the Perl6 spigot or Machin methods below will be pretty fast. They are not too bad if the Math::BigInt::GMP library is installed. With the default Math::BigInt backend, the AGM code isn't very fast and the Perl6 spigot and Machin methods are very slow.

This takes a numer-of-digits argument, but we can make it large (albeit using memory and some startup time). Unlike the other two, this uses no modules and does not require bigints so is worth showing.

Here is an original Perl 5 code, using Machin's formula. Not the fastest program in the world. As with the previous code, using either Math::GMP or Math::BigInt::GMP instead of the default bigint Calc backend will make it run thousands of times faster.

Uses the GMP big int library.
Same algorithm as many of the others on this page. Uses in place ops to cut down on big int generation (eg add vs +). Unless GC is given some hints, it will use up 16 gig quickly as it outruns the garbage collector.