Reply To: Recursion help – beginner

Home Forums Basic Erlang Recursion help – beginner Reply To: Recursion help – beginner

#54907

zsoci
Member

Thanks to Tomasz for the clear description of the formula. Although I have my math background it was long time ago when I learned it.

From the above I do not see any more pointers to follow, so to help Makhdum understand the details let us make it as an erlang function step by step.

As Tomasz showed, this is an iteration where we want to add (subtract in every other step) a value that gets smaller and smaller in each step. This is rather a loop than a real recursion but in Erlang, loops are constructed with tail recursion.

Lets take a look at the first couple of steps:
1. A1 = 4-4/3
2. A2 = A1 + 4/5 ……… 4-4/3+4/5
3. A3 = A2 – 4/7
and so on. When Ai is precise enough, lets say 5 decimals are not changing any more as we found the precision we were looking for.

Basically we need to set a loop that calculates the next element (Ai) by adding (or subtracting) the changing 4/x in each step.

Initially we have the value as 4, the numerator is 4 (and will stay as it is) and the denominator is 1. With these values we can calculate the next value by having NextValue = CurrentValue – Numerator/(Denominator + 2). With real values it is NextValue = 4-4/(1+2) thus exactly what we have in step 1 above.

When our NextValue and CurrentValue has difference that not bigger that our precision needs, we are done.

If we need to go further, we shall continue the calculation but with NewValue as the Value, Numerator changes sign to alternate addition and subtractions but the next Denominator will be the currentdenominator+2 as to perform the next step. In our second step
Numerator will be -4 and denominator will be 3 so the formula will be: NextValue = (4 – 4/(1+2)) + 4/(3+2). This is what we have in step 2 above.

If you got the point, it will be easy to understand the erlang code as follows:

calc_pi(DecPlaces) ->
    iterate(math:pow(10,DecPlaces),4,1,4)
.

iterate(Precision,Numerator,Denominator,CurrentValue) ->
    NextValue = CurrentValue - Numerator/(Denominator + 2),
    if
        round(NextValue * Precision) / Precision =:= 
        round(CurrentValue * Precision) / Precision ->
%             io:format("Numerator=~p, Denominator=~p, CurrentValue=~p,NextValue=~p~n",[Numerator,Denominator,CurrentValue,NextValue]),
              {round(NextValue * Precision) / Precision,(Denominator + 1) div 2};
        true ->
            iterate(Precision,-Numerator,Denominator + 2,NextValue)
	end
.

Feel free to post questions on specifics if you need more details.