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.