1

I want to implement this square root method in Pascal using recursion. However, I have some problems understanding how to transfer iterative method into recursive method:

Program NewtonRaphsonRecursive(output);

{$mode objFPC}

function newton_raphson_rec(a: real; p: real; eps: real; max_i: integer) : real;
var
    x: real;
    i: integer;
begin
    x := a / 2.0;
    i := 0;
    
    if abs(x - a / x) < eps then
        begin
             result := x;
        end
    else
        begin
            x := (x + a / x) / 2.0;
            i := i + 1;
            result := newton_raphson_rec(x, p, eps, max_i);
        end;
end;

var
    sqroot: real;
begin
  
  sqroot := newton_raphson_rec(25, 0.001, 0.000001, 100);
  writeln(sqroot);
  
end.

The code: https://onlinegdb.com/OvDBfHzLf

LU RD
  • 34,438
  • 5
  • 88
  • 296
Brian Brown
  • 3,873
  • 16
  • 48
  • 79
  • 2
    Hint: First of all, the iteration (or recursion) should stop when max_i iterations has been done or the eps comparison is fulfilled. – LU RD Jan 02 '22 at 14:17
  • @LURD: But how to stop recursion in Pascal? – Brian Brown Jan 02 '22 at 14:18
  • 1
    As I said, each time the recursion is called, decrement the max_I parameter. Test for max_I < 1 and the eps comparison. If any of them is true, you quit with the existing result. – LU RD Jan 02 '22 at 14:27
  • @LURD: I changed this like you suggested, but the result is quite wrong: https://onlinegdb.com/UpDmPmCiq. For `25` it shows `6.667`. – Brian Brown Jan 02 '22 at 19:24
  • Well, I was just giving you a hint how to take a step forward. See my answer. – LU RD Jan 02 '22 at 21:32
  • Recursion operates on the same basic principles as imperative iteration. You have a starting state, an exit condition that causes termination of recursion/iteration, and an update that updates the state to converge on that exit condition. – Chris Jan 02 '22 at 21:34

2 Answers2

3

If you look at the start of the Newton-Raphson iterative solution in the other question, you will see that the first calculation (x := num / 2.0) is merely a first guess of the solution. You must remove that line in your recursive solution and enter a best guess into the function parameter.

function newton_raphson_recurse(num: real; new_guess: real; eps: real; max_i: integer) : real;
begin
  Dec(max_i); // Decrement counter
  new_guess := (new_guess + num / new_guess) / 2.0;
  if (Abs(new_guess - num) < eps) or (max_i < 1)
    then Result := new_guess
    else Result := newton_raphson_recurse(num,new_guess,eps,max_I);
end;

...
sqroot := newton_raphson_recurse(9, 9/2.0, 0.0000001, 10);

Note how the new_guess is reused during the recursion with a more accurate value each time.

As always when testing a routine, single stepping into the program is a very good skill to learn when debugging.

LU RD
  • 34,438
  • 5
  • 88
  • 296
2

Recursion operates on the same basic principles as imperative iteration. You have a starting state, an exit condition that causes termination of recursion/iteration, and an update that updates the state to converge on that exit condition.

Consider a simple example: summing a range.

function SumImperative(s, e : integer) : integer;
var
  current : integer;
  result : integer;
begin
  current := s;
  result := 0;

  while current <= e do
  begin
    result := result + current;
    current := current + 1
  end;

  SumImperative := result;
end;

Our function sets an initial state, the while current <= e do sets an exit condition, and current := current + 1 updates the state.

Now, recursively...

function SumRecursive(s, e : integer) : integer;
begin
  if s > e then
    SumRecursive := 0
  else
    SumRecursive := s + SumRecursive(s + 1, e)
end;

Here we set our initial state with the fucntion arguments. Our exit condition is s being greater than e. If that happens, the function returns 0 and there is no more recursion. If that codnition isn't met, we add s to the result of calling the fucntion again, but this time we update the state so that we're looking for s + 1 and e.

This looks like:

SumRecursive(1, 4)
1 + SumRecursive(2, 4)
1 + (2 + SumRecursive(3, 4))
1 + (2 + (3 + SumRecursive(4, 4)))
1 + (2 + (3 + (4 + SumRecursive(5, 4))))
1 + (2 + (3 + (4 + 0)))
1 + (2 + (3 + 4))
1 + (2 + 7)
1 + 9
10
Chris
  • 26,361
  • 5
  • 21
  • 42