11. recursion

advertisement
Introduction to Programming
MAT190
Copyright 2007-08 by Dr. Milica Barjaktarovic
This textbook in making contains notes and descriptions, study questions, and coding problems.
There are sections for more interested students, which can be skipped by a beginning reader.
11. RECURSION
Recursive functions call themselves. A classic example is n!.
n! = n (n-1)!
In other words, f(n) = n*f(n-1).
There are many other recursive functions. Recursion is used a lot in designing programs, because it
is closer to how people think. However, in efficient implementations, recursion is substituted by
iteration. The reason is that recursive code uses too much memory space (every time we call a
function within function, it is stored in a stack in the memory, and the stack can overflow).
The following are different (literal) implementations of n!, in C-like pseudocode:
RecFact(n)
{
If n==0
return 1
else
return n*RecFact(n-1)
}
At the level of skill we have with FORTRAN now, we cannot even code this, because it requires
calling the same function again. We don’t know subprograms yet. So, we will leave coding this later.
FYI: I haven’t found a way to code this in FORTRAN as is. !!! This severely limits the language. C
or Java would allow this. In fact, the above is code in C.
Also, we do NOT really want to code like this, because when functions call themselves, it can lead
to stack overflow, i.e. errors. So, let’s try iterative version. The one below is in C-like pseudocode:
IterativeFact(n) {
if n==0
return 1
y = n
i = n
while (i>0)
{
y = y*(i-1)
i=i-1
}
return y
Factorial code in FORTRAN:
PROGRAM iterativefact_backward
INTEGER:: n, y
PRINT *, “This program calculates n!. Please enter n.”
READ *,n
IF (n == 0) THEN
PRINT *, 1
ELSE
y = n
! since we are starting from n, the next thing to multiply with is
n-1, so that’s why we are starting with n-1. We can skip 1 and go
down only to 2, because multiplying with 1 does not change
anything. The increment has to be negative. Notice how this formula
goes backwards, it starts from the top and goes down, i.e. starts
from the last number and goes backwards to the first number.
!
!
DO I = n-1, 2,-1
y = y* I
for debugging purposes, print the current values
PRINT *, I, y
END DO
this is the final value
PRINT *, y
END IF
END PROGRAM iterativefact_backward
Of course, the whole thing CAN be coded going forward, as shown below. However, we want to
make sure that we understand coding backwards, because that’s the way that truly recursive
code works. Notice that we are coding a recursive formula, and so far we have seen 3 different
ways to code it.
PROGRAM iterativefact_forward
INTEGER:: n, y
PRINT *, “This program calculates n!. Please enter n.”
READ *,n
IF (n == 0) THEN
PRINT *, 1
ELSE
y = 1
!
This version codes forward
DO I = 2,n
y = y* i
for debugging purposes, print the current values
PRINT *, I, y
!
END DO
!
this is the final value
PRINT *, y
END IF
END PROGRAM iterativefact_forward
ASSIGNMENT 11:
Submit pencil-and-paper conformation of your test runs, i.e. submit paper-and-pencil test cases and
calculations as well as code test cases and results, and confirm if they match.
1. Write a program that factorizes an integer into primes using Pollard P-1 method.
k is a factor on n iff we have n mod k = 0.
http://mathforum.org/library/drmath/view/65801.html
2. Find roots of a polynomial using Newton method.
http://www.math.hawaii.edu/~dave/m190_assign9.pdf
This handout has some very nice examples and explanations. Note that we didn’t study subprograms yet so
you will have to have all the code in the main program, i.e. ignore all comments about subprograms.
The assignment is to find the root of polynomial of order n, i.e. the value of x for which the polynomial
evaluates to 0. So far we found roots of polynomial of order 2, i.e. quadratic equation. If the polynomial is of
order n, then the formula for finding such x is recursive.
The approach can be described as “start from somewhere and try to get closer.”
First we just pick some arbitrary x1, and then calculate the next value using this formula:
xm+1 = x m – p(x m)/p’(xm)
Note that Dr. Steganga’s handout uses n instead of m, but that could confuse some students because
that n is not the same n used as the degree of the polynomial below.
m goes from 1 to a specified K, where K is the number of recursive iterations we want. (It is
different than the k we will use below for the polynomial!)
(Notice that this approach is slightly different than n! recursion, because n! starts from the end and goes to the
bottom. This formula starts from the bottom.)
p(x m) is calculated using your polynomial code, as
n
p(x) =
 ak x k
= a1 x1 + a2 x2 + a3 x3 + … + an xn
k=1
which we will write out in “plain text” notation as:
p(x)
= SUM[k=1, n] ak xk
So, just copy in your polynomial code and feed it the value of x m.
The derivative of the polynomial is just slightly different, so also reuse your polynomial code:
n
p’(x) =
 k ak xk-1
= a1 x1-1 + 2a2 x2-1 + 3a3 x3-1 + … + n an xn-1
k=1
p’(x)
= SUM[k=1, n] kak xk-1
If p’(x) =0, then print the error message to the user, Newton method does not work.
So, follow this algorithm:
! Read in the coefficients ak and the degree n of the polynomial from the user
! Read in the number of iterations, K
! Read in the starting x1
! Calculate the root of the polynomial by repeating the formula from 1 to K.
Download