Question

I have been given this question to work on a solution. I'm struggling to get my head around the recursion. Some break down of the question would be very helpful.

Given that Pi can be estimated using the function 4 * (1 – 1/3 + 1/5 – 1/7 + …) with more terms giving greater accuracy, write a function that calculates Pi to an accuracy of 5 decimal places.

I have got some example code however I really don't understand where/why the variables are entered like this. Possible breakdown of this code and why it is not accurate would be appreciated.

-module (pi).
-export ([pi/0]).

pi() -> 4 * pi(0,1,1).

pi(T,M,D) ->
    A = 1 / D,
    if 
        A > 0.00001 -> pi(T+(M*A), M*-1, D+2);
        true -> T 
    end.
Was it helpful?

Solution

The formula comes from the evaluation of tg(pi/4) which is equal to 1. The inverse:

pi/4 = arctg(1)
so
pi = 4* arctg(1).
using the technique of the Taylor series:
arctg (x) = x - x^3/3 + ... + (-1)^n x^(2n+1)/(2n+1) + o(x^(2n+1))
so when x = 1 you get your formula:
pi = 4 * (1 – 1/3 + 1/5 – 1/7 + …)

the problem is to find an approximation of pi with an accuracy of 0.00001 (5 decimal). Lookinq at the formula, you can notice that at each step (1/3, 1/5,...) the new term to add:

  • is smaller than the previous one,
  • has the opposite sign.

This means that each term is an upper estimation of the error (the term o(x^(2n+1))) between the real value of pi and the evaluation up to this term. So it can be use to stop the recursion at a level where it is guaranty that the approximation is better than this term. To be correct, the program you propose multiply the final result of the recursion by 4, so the error is no more guaranteed to be smaller than term.

looking at the code:

pi() -> 4 * pi(0,1,1).
%  T = 0 is the initial estimation
%  M = 1 is the sign
%  D = 1 initial value of the term's index in the Taylor serie

pi(T,M,D) ->
    A = 1 / D,
% evaluate the term value
    if 
        A > 0.00001 -> pi(T+(M*A), M*-1, D+2);
%  if the precision is not reach call the pi function with, 
%  new serie's evaluation (the previous one + sign * term): T+(M*A)
%  new inverted sign: M*-1
%  new index: D+2
        true -> T
%  if the precision is reached, give the result T           
    end. 

To be sure that you have reached the right accuracy, I propose to replace A > 0.00001 by A > 0.0000025 (= 0.00001/4)

OTHER TIPS

I can't find any error in this code, but I can't test it right now, anyway:

T is probably "total", M is "multiplicator", and D is "divisor". By every step you:

  • check (the 'if' is in some way similar to a switch/case in c/c++/java) if the next term (A = 1/D) is bigger than 0.00001. If not, you can stop the recursion, you've got the 5 decimal places you were looking for. So "if true (default case) -> return T"

  • if it's bigger, you multiply A by M, add to the total, then multiply M by -1, add 2 to D, and repeat (so you get the next term, add again, and so on).


pi(T,M,D) ->
A = 1 / D,
if 
    A > 0.00001 -> pi(T+(M*A), M*-1, D+2);
    true -> T 
end.

I don't know Erlang myself but from the looks of it you are checking if 1/D is < 0.00001 when in reality you should be checking 4 * 1/D because that 4 is going to be multiplied through. For example in your case if 1/D was 0.000003 you would stop four function, but your total would actually have changed by 0.000012. Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top