Calculate PI digits (arbitrary-precision) using Python


We are going to calculate PI number with an arbitrarily high precision.


We copy following code in a file. e.g: pi_digits.py

Then we will execute it like this:

$ python3 pi_digits.py 100
PI: 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068



#!/usr/bin/python3

# Calculate PI number using this formula:
# x[n+1] = x[n] + sin(x[n])
#
# x[n+1] = x[n] + x[n] + x[n]**3/fact(3) - x[n]**5/fact(5) + x[n]**7/fact(7) - x[n]**9/fact(9) + ....

from decimal import getcontext, Decimal
import sys

if len(sys.argv) < 2:
    print('Not enough arguments')
    quit()

precision = int(sys.argv[1])
excess_prec = 2

prec_cur = 100 if precision > 100 else precision

getcontext().prec = prec_cur + excess_prec

second = Decimal(3)  # Current element for PI
queue_cur = [Decimal(0), Decimal(0), Decimal(0), second]

qq_append = queue_cur.append
qq_pop = queue_cur.pop

limit = Decimal(10) ** (-prec_cur - excess_prec)

while True:

    sec_sq = second * second
    term = second
    acc = second + term
    count = Decimal(1)

    while term > limit:

        term *= sec_sq / ((count + 1) * (count + 2))
        acc -= term
        # print ('term1: {}'.format(term))

        term *= sec_sq / ((count + 3) * (count + 4))
        acc += term

        count += 4
        # print ('term2: {}'.format(term))

    # print ('acc: {}'.format(second))
    if acc in queue_cur:
        if prec_cur < precision:
            prec_cur += prec_cur
            if prec_cur > precision:
                prec_cur = precision
            limit = Decimal(10) ** (-prec_cur - excess_prec)
            getcontext().prec = prec_cur + excess_prec

        else:
            second = acc
            break

    qq_append(acc)
    qq_pop(0)
    second = acc
    # print ('second: {}'.format(second))

getcontext().prec = precision
print("PI: ", +second)




This code runs this formula recursively:
x[n+1] = x[n] + sin(x[n])

When near PI number (e.g: 3) it converges to PI.


sin(x) function is also calculated using a Taylor series: https://en.wikipedia.org/wiki/Taylor_series

sin(x) = x - (x**3)/factorial(3) + (x**5)/factorial(5) - (x**7)/factorial(7) ...


So our formula to calculate PI becomes:

x[n+1] = x[n] + x[n] - (x[n]**3)/factorial(3) + (x[n]**5)/factorial(5) - (x[n]**7)/factorial(7) + ...



Code starts calculations using 100 digits of precision, and duplicates it until it reaches precision specified in command line.



Let's test the script with a bigger precision: 500000 digits of PI