Reputation: 5
pi/2 = 1 + 1/3 + (1*2) / (3*5) + (1*2*3) / (3*5*7) + ...
Okay, let's try this again.
I need to write a function that takes the max error as a parameter for the value of pi and returns the calculated value of pi and the number of iterations necessary to get to that point. I can't use a recursive algorithm.
Thus far I have:
def piEuler (x):
count = 0.0
approx = 0.0
approx2 = 1.0
error = math.pi/2 - approx2
while error > x:
count = count + 1
approx3 = approx + approx2
error = math.pi/2 - approx3
#print error
approx = approx + approx2
approx2 = approx2 * count/(count + 2)
#print approx2
final = math.pi - error
return final, count
The issue is that the program is returning a negative value. The error should converge to zero. I need to be able to subtract my error from the accepted value of pi to get an approximate value from the series. What am I doing wrong?
Upvotes: 0
Views: 4372
Reputation: 548
You should try to rewrite the routine such that the smallest term in the sequence, approx2 in your code, has to be greater than error.
Also you have 'math.pi' in your last error calculation. Does it have to be math.pi/2 ?
It seems the nature of the error is oscillating also!
Upvotes: 0
Reputation: 24788
It looks like you were incorrectly implementing the algorithm. Rather than doing pi/2 = 1 + 1/3 + (1*2)/(3*5) + (1*2*3)/(3*5*7) + ...
, it looks like your code is doing pi/2 = 1 + 1/3 + (1*2)/(3*4) + (1*2*3)/(3*4*5) + ...
.
Since the denominators will end up being smaller, you'll be increasing the sum by a greater amount, resulting no doubt in an overshoot and consequently a negative error.
The problem lies in this line:
approx2 = approx2 * count/(count + 2)
As you can see, when count
is even, count + 2
will be even. An easy fix would be to change this to:
approx2 = approx2 * count/(2 * count + 1)
Here is a example algorithm that works, but uses the relative error between terms rather than the absolute error (wouldn't want to give everything away ;) ):
from __future__ import division
def half_pi(max_err=10**-6, max_iter=10000):
partial_sum = cur_term = 1
n = 1
while abs(t) > max_err and n < max_iter:
cur_term = cur_term * (n / (2 * n + 1))
partial_sum += cur_term
n += 1
return partial_sum, n
Upvotes: 1
Reputation: 19671
This works:
import math
def piEuler(x):
halfpi = math.pi / 2.0
count = 0
approx = 1.0
divisor = 1
numerator = 1
while True:
count += 1
numerator *= count
divisor *= 2*count + 1
approx += float(numerator) / float(divisor)
error = halfpi - approx
if error < x:
return (math.pi - error), count
The basic differences are:
Upvotes: 2