This is a task for a programming course. We need to approximate π using 2 different functions. 1 uses Gregory-Leibniz theory, the other Madhava of Sangamagrama's . Both of these aren't any problem, but the third function is giving me some trouble. :
Examine which of both sequences converges the fastest. Use this sequence to write a function approach_pi. This function should allow to determine an approached value of π , that is precise to n decimals. The value n should be given as an argument of the function. To determine the accuracy of the approach, you should check whether the difference between two consecutive terms in the sequence is smaller than 10^-n-1. When the difference between the (i-1)th and the i-th term becomes smaller than 10^-n-1, the i-th partial sum forms an approach of π to (n) decimals precisely. The function should give the tuple (i, p) as a result, i is the number of calculated terms and n is the approached value of π.
following part is my code:
def GL(n):
a, pi, flag = 1, 0, True
while a <= (n*2-1):
if flag:
pi += (4/a)
else:
pi -= (4/a)
flag = not flag
a += 2
return pi
def MvS(n):
flag, a, parentheses, i = True, 3, 1, 1
while a <= (n*2-1):
if flag:
parentheses -= (1/(a*3**i))
else:
parentheses += (1/(a*3**i))
i += 1
a += 2
flag = not flag
return math.sqrt(12)*parentheses
def approach_pi(n):
counter_GL, counter_MvS, i = 0, 0, 2
while 10**(-n-1) > GL(i-1) - GL(i) > (-10**(-n-1)):
counter_GL += 1
i += 1
i = 2
while 10**(-n-1) > MvS(i-1) - MvS(i) > (-10**(-n-1)):
counter_MvS += 1
i += 1
return counter_GL, counter_MvS, GL(i)
x = int(input("give n : "))
print(approach_pi(x))
I know the last function is not at all correct but I'm out of ideas. Could someone explain me the proper reasoning for this problem?
Some example solutions are: approach_pi(3): (10, 3.14159051093808) approach_pi(2): (8, 3.141568715941784) approach_pi(6): (16, 3.1415926517339976)
This becomes a lot more efficient if you build your functions as generators, so you don't have to rerun the entire sequence every time.
Computing closeness is just a matter of if abs(this - lastthis) < epsilon
.
This seems to work, and it shows how bad the Gregory-Leibniz method is:
import math
def GL():
a, pi, flag = 1, 0, True
while True:
if flag:
pi += (4/a)
else:
pi -= (4/a)
flag = not flag
a += 2
yield pi
def MvS():
flag, a, parentheses, i = True, 3, 1, 1
yield 3
while True:
if flag:
parentheses -= (1/(a*3**i))
else:
parentheses += (1/(a*3**i))
i += 1
a += 2
flag = not flag
yield math.sqrt(12)*parentheses
def approach_pi(n):
epsilon = 10**(-n)
oldg = 0
oldm = 0
for i,gm in enumerate(zip(GL(), MvS())):
g,m = gm
print(i,g,m)
if abs(g-oldg) < epsilon:
print( "GL converges at step", i )
return i+1,g
if abs(m-oldm) < epsilon:
print( "MvS converges at step", i )
return i+1,m
oldg,oldm = g,m
approach_pi(6)
You can eliminate the "flags" by unrolling the loops:
import math
def GL():
a, pi = 1, 0
while True:
pi += (4/a)
a += 2
yield pi
pi -= (4/a)
a += 2
yield pi
def MvS():
parentheses, a, denom = 1, 3, 3
yield 3
while True:
parentheses -= (1/(a*denom))
a += 2
denom *= -3
yield math.sqrt(12)*parentheses
def approach_pi(n):
epsilon = 10**(-n)
oldg = 0
oldm = 0
for i,gm in enumerate(zip(GL(), MvS())):
g,m = gm
print(i,g,m)
if abs(g-oldg) < epsilon:
print( "GL converges at step", i )
return i+1,g
if abs(m-oldm) < epsilon:
print( "MvS converges at step", i )
return i+1,m
oldg,oldm = g,m
approach_pi(6)