# Calculating π ( Pi ) with Python

For fun I decided to write a python script to calculate the mathematical constant $\pi$ (Pi). Here’s my code


# Date: January 4, 2014
from decimal import *
import math

class PiCalculator(): #Calculates Pi
def __init__(self, prec):
getcontext().prec = prec # the precision
return

def nilakantha(self, end): # Nilakantha's series
op = '+'
x = Decimal(3)
for n in range(2, end, 2):
if (op == '-'):
x -= ( Decimal(4) / Decimal((n * (n+1) * (n+2))) )
op = '+'
else:
x += ( Decimal(4) / Decimal((n * (n+1) * (n+2))) )
op = '-'
return x

def gregory_leibniz(self, end): # Gregory-Leibniz's series
op = '+'
x = Decimal(0)
for n in range(1, end):
if (op == '-'):
x -= ( Decimal(4) / Decimal(2*n - 1) )
op = '+'
else:
x += ( Decimal(4) / Decimal(2*n - 1) )
op = '-'
return x

def ramanujan(self, end): # Ramanujan's series
y = Decimal(0)

for n in range(0, end):
y += ( Decimal(math.factorial(4*n)) * Decimal((1103 + 26390*n)) )\
/ (Decimal(math.pow( Decimal(math.factorial(n)), 4)) \
* Decimal(math.pow(396, 4*n)) )
y *= ( Decimal(2) * Decimal(math.sqrt(2)) ) / Decimal(9801)

y = Decimal(1/y)
return y

def chudnovsky(self, end):
y = Decimal(0)

for n in range(0, end):
y += ( Decimal(math.factorial(6*n)) * \
Decimal((13591409 + 545140134*n)) )\
/ ( Decimal(math.pow( \
Decimal(math.factorial(3*n)) * Decimal(math.factorial(n)), 3)) \
* Decimal(math.pow(-640320, 3*n)) )

y *= ( Decimal(12) / Decimal(math.pow(640320, 1.5)) )

y = Decimal(1/y)
return y

def in_built(self): # Stored Value by Python implementation
return Decimal(math.pi)



I did a test-run allowing ten iterations to each method:

def main():

calc_pi = PiCalculator(10**3)

pi_s = calc_pi.in_built()
pi_n = calc_pi.nilakantha(10)
pi_gl = calc_pi.gregory_leibniz(10)
pi_r = calc_pi.ramanujan(10)
pi_c = calc_pi.chudnovsky(10)

separator = "\n\n\n********\n\n"

print("Stored Value: ", pi_s, separator)
print("Nilakantha: ", pi_n, separator)
print("Gregory-Leibniz: ", pi_gl, separator)
print("Ramanujan: ", pi_r, separator)
print("Chudnovsky: ", pi_c, separator)
input("press any key to continue")
return

main()



I compared my results with this. The Gregory-Leibniz method was accurate only to the first digit. Nilakantha to the first 2 digits. Chudnovsky was accurate to the first 14 digits and Ramanujan’s method turned out to be the best so far by yielding 16 accurate digits.

Next, I decided to give the Nilakantha and Gregory-Leibniz methods a bit of an advantage by allowing then $10^4$ iterations each, while I increased the iterations of the Chudnovsky and Ramanujan to only 15.


pi_s = calc_pi.in_built()
pi_n = calc_pi.nilakantha(10**4)
pi_gl = calc_pi.gregory_leibniz(10**4)
pi_r = calc_pi.ramanujan(15)
pi_c = calc_pi.chudnovsky(15)



This time Gregory-Leibniz was accurate to the first 4 digits and Nilakantha to the first 11 digits. Chudnovsky’s and Ramanujan’s methods still gave an accuracy of 14 digits and 16 digits respectively.

Overall, it was a pretty educational experience. I found out that for the number of iterations I tried out (unless I made a mistake), the methods, in order of decreasing accuracy are:

• Ramanujan — 16 digits on 15 iterations (Most Accurate)
• Chudnovsky — 14 digits on 15 iterations
• Nilakantha — 11 digits on $10^4$ iterations
• Gregory-Leibniz — 4 digits on $10^4$ iterations (Least Accurate)