Brian Brown
Brian Brown

Reputation: 4311

Newton-Raphson method (square root) in Pascal, recursion

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

Upvotes: 1

Views: 568

Answers (2)

LU RD
LU RD

Reputation: 34919

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.

Upvotes: 3

Chris
Chris

Reputation: 36611

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

Upvotes: 2

Related Questions