Scope of Variables The variables used in function m-files are known as local variables. Any variable defined within the function exists only for the function to use. The only way a function can communicate between other functions is through input arguments and the outputs it returns. Unlike local variables, global variables are available to all parts of a computer program. Use global to declare x as a global variable. In general, it is not a good practice to define many global variables. 1 For example, the universal constant, say,. 2 However, you have to take the responsibly of not changing its value. 1 This violets the modularity. 2 Planck constant = 1.055 10 34 in Quantum theories. Zheng-Liang Lu 188 / 227
Example: Local Variables 1 clear; clc; 2 3 x = 0; 4 for i = 1 : 10 5 addone(x); 6 disp(x); 7 end 1 function addone(x) 2 x = x + 1; 3 end What are the numbers shown? If you want the sequence 1, 2,..., 10, then how can you do? (Local, global, persistent?) Zheng-Liang Lu 189 / 227
Example: Global Variable 1 function h = falling(t) 2 global GRAVITY 3 h = 1 / 2 * GRAVITY * t.ˆ 2; 4 end 1 clear; clc; 2 global GRAVITY 3 GRAVITY = 9.8; 4 y = falling(0 : 0.1 : 5); What if you take global out of the function? As a more robust alternative, redefine the function to accept GRAVITY as an input. Zheng-Liang Lu 190 / 227
Types of User-Defined Functions Primary functions and subfunctions Anonymous functions Nested functions Private functions Zheng-Liang Lu 191 / 227
Primary Functions and Subfunctions A function m-file may contain more than one user-defined function. The first defined function in the file is called the primary function, whose name is the same as the m-file name. All other functions in the file are called subfunctions. Subfunctions are normally visible only to the primary function and other subfunctions in the same file. Note that the order of the subfunctions does not matter, but function names must be unique within the m-file. Zheng-Liang Lu 192 / 227
Example 1 function [a c] = circle(r) % primary function 2 a = area(r); 3 c = perimeter(r); 4 end 5 6 function y = area(x) % subfunction 1 7 y = pi * x.ˆ 2; 8 end 9 10 function v = perimeter(u) % subfunction 2 11 v = 2 * pi * u; 12 end Zheng-Liang Lu 193 / 227
1 >> [a c] = circle(2) 2 3 a = 4 5 12.5664 6 7 8 c = 9 10 12.5664 Recall that if only one variable is assigned as output of the function, say, circle, then the area is returned while the perimeter is ignored. Zheng-Liang Lu 194 / 227
Example: Alternative to Infinite Loops 3 One subfunction can be called by other subfunctions in addition to the primary function. 1 function test1 2 fprintf('hi, there. This is test1.\n'); 3 test2; 4 end 5 6 function test2 7 fprintf('hi, there. This is test2.\n'); 8 test1; 9 end Notice that two subfunctions calling each other can lead to a loop, resulting a fatal crash. 3 Thanks to a lively class discussion (MATLAB-238) on June 14, 2014. Zheng-Liang Lu 195 / 227
Anonymous Functions Anonymous functions enable you to create a simple function without needing to create an m-file for it. Anonymous functions are so-called the function handles, defined by @. For example, 1 >> f = @(x) x.ˆ 2 + x + 1 % x.ˆ2 allows vectorization. 2 >> f([1 10]) 3 4 ans = 5 6 3 111 Furthermore, you can make the existing function a function handle by using the @ operator, for example, y = @sin. Zheng-Liang Lu 196 / 227
You can create anonymous functions having more than one input. One anonymous function can call another to implement function composition. 1 >> f = @(x, y) sqrt(x.ˆ 2 + y.ˆ 2); % f is a function... handle 2 >> g = @(x, y) f(x, y).ˆ 2; % g is a composite function 3 >> g(3, 4) 4 5 ans = 6 7 25 Zheng-Liang Lu 197 / 227
More Examples 6 Give input values, return a function handle. 4 For example, 1 function y = f(a, b, c) 2 y = @(x) a * x.ˆ 2 + b * x + c; 3 end Give a function handle as input, return a value. 5 For example, 1 function y = diff(f, x) 2 eps = 1e-9; 3 y = (f(x + eps) - f(x))./ eps; 4 end Give a function handle as input, return a function handle? (Try.) 4 Contribution by Ms. Queenie Chang (MAT25108) on March 18, 2015. 5 Thanks to a lively class discussion (MATLAB-260) on September 16, 2015. 6 Thanks to a lively class discussion (MATLAB-244) on August 22, 2014. Zheng-Liang Lu 198 / 227
Nested Functions Functions are said to be nested if the functions are defined within the parent function. A nested function can access the variables of its parent function. 1 function f = parabola(a, b, c) 2 f = @p; %f is a function handle of p 3 function y = p(x) % p shares a, b, and c 4 y = a * x.ˆ2 + b * x + c; 5 end 6 end Zheng-Liang Lu 199 / 227
1 >> y = parabola(1, 2, 1); 2 >> y(5) 3 4 ans = 5 6 36 Note that the nested functions are defined anywhere within the main function. (Why?) Zheng-Liang Lu 200 / 227
Private Functions Private functions are useful when you want to limit the scope of the function. A private functions resides in subfolder with the special name private. The private function is visible only to functions in the parent directory. Note that you cannot call the private function from the command line or from functions outside the parent of the private folder. Zheng-Liang Lu 201 / 227
Precedence When Calling Functions 1 Nested functions 2 Subfunctions within the same file 3 Private functions 4 Local functions in the same directory 5 Built-in functions 6 Standard m files in PATH Zheng-Liang Lu 202 / 227
Example: Bisection Method The bisection method in mathematics is a root-finding method that repeatedly bisects an interval and then selects a subinterval in which a root must lie for further processing. (Why?) It is often used to obtain an approximate solution. Zheng-Liang Lu 203 / 227
Zheng-Liang Lu 204 / 227
Outline for Bisection Method 1. At each step, the algorithm divides the interval in two by computing the midpoint c = (a + b)/2 of the interval and the value of the function f (c) at that point. 2. Unless c is itself a root (which is very unlikely, but possible), there are now two possibilities: either f (a) and f (c) have opposite signs and bracket a root, or f (c) and f (b) have opposite signs and bracket a root. Zheng-Liang Lu 205 / 227
3. The method selects the subinterval that is a bracket as a new interval to be used in the next step. 4. In this way the interval that contains a zero of f is reduced in width by 1 2 at each step. 5. The process is continued until the interval is sufficiently small. 7 7 How small? A certain number you give is to be the stop criteria. Zheng-Liang Lu 206 / 227
Problem Formulation Input - Target function f (x) - Endpoints of the interval [a, b] for any real numbers a < b - Minimal interval length ɛ = b a Output - the approximate root ˆr Note that a and b will be updated iteratively. Zheng-Liang Lu 207 / 227
Solution 1 clear; clc; format long; 2 3 a = input('a =?\n'); 4 b = input('b =?\n'); 5 f = @(x) x.ˆ 3 - x - 2; % target function 6 eps = 1e-9; 7 iter = 0; % the number of iterations 8 9 if f(a) == 0 10 r = a; % lucky a 11 elseif f(b) == 0 12 r = b; % lucky b 13 else 14 while b - a > eps 15 iter = iter + 1; 16 c = (a + b) / 2; % middle point 17 if f(c) == 0 Zheng-Liang Lu 208 / 227
18 r = c; % lucky c 19 break; 20 elseif (f(a) * f(c) < 0) 21 b = c; 22 elseif (f(b) * f(c) < 0) 23 a = c; 24 else 25 error('failure: f(a) * f(c) > 0 and f(c) *... f(b) > 0.'); 26 end 27 fprintf('%d: %f\n', iter, c); 28 end 29 r = c % approximate solution 30 end Zheng-Liang Lu 209 / 227
4 3 2 1 0 1 2 3 1 0.5 0 0.5 1 1.5 2 c = 1.52137970691547 Zheng-Liang Lu 210 / 227
Remarks Time complexity: O(log 2 n) What is n? In this case, n = b a. (Why?) ɛ So, it is an algorithm which runs in log time. This means that you need to make a trade-off between the numerical precision and the computation time. Be aware that this algorithm works well only with the premise that the behavior in [a, b] is mild. Approximate solutions may be significantly influenced by the initial interval [a, b]. 8 f (c) 0 but not equal to exactly 0. (Why?) 8 You may try another algorithm for the root finding problem, say, the Newton-Raphson method. Zheng-Liang Lu 211 / 227
Exercise Make your bisection method algorithm into a user-defined function, say, bisection. So, you can call bisection to find a root for a specific function in the command window or other programs. Besides, you should extend the function with more input arguments for parameters used in bisection. Zheng-Liang Lu 212 / 227
Problem Formulation Input - Target function f (x) - Endpoints of the interval [a, b] for any real numbers a < b - Minimal interval length ɛ = b a Output - The approximate root ˆr Zheng-Liang Lu 213 / 227
1 function r = bisection(f, a, b, eps) 2 3... 1 >> bisection(@(x) x.ˆ 3 - x - 2, 0, 3, 1e-9) 2 3 ans = 4 5 1.5214 Zheng-Liang Lu 214 / 227
Recursive Functions Recursion is when something is defined in terms of itself. A recursive function is a function that calls itself. Recursion is an alternative form of program control. It is essentially repetition without a loop. Zheng-Liang Lu 215 / 227
Example The factorial of a non-negative integer n, denoted by n!, is the product of all positive integers less than or equal to n. For example, 4! = 4 3 2 1 = 4 3! So we can say f (n) = n f (n 1), for n > 0. Also, we need a base case such that the recursion can stop instead of being an infinite loop. In this example, 0! = 1. Zheng-Liang Lu 216 / 227
Exercise Write a program which determines return a factorial of n. 1 function y = recursivefactorial(n) 2 if n > 0 3 y = n * recursivefactorial(n - 1); 4 else 5 y = 1; % base case 6 end 7 end We can use a loop to calculate n!. (Try.) Zheng-Liang Lu 217 / 227
Call Stack Zheng-Liang Lu 218 / 227
Equivalence 1 function y = loopfactorial(n) 2 y = 1; 3 for i = n : -1 : 1 4 y = y * i; 5 end 6 end One more intriguing question is, Can we always turn a recursive method into an iterative one? Yes, theoretically. 9 Which is better? 9 The Church-Turing thesis proves it if the memory serves. Zheng-Liang Lu 219 / 227
Example: Fibonacci Numbers 10 The Fibonacci sequence is a sequence with the following pattern: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34.... Alternatively, the Fibonacci sequence is defined by the recurrence relation F n = F n 1 + F n 2, where F 0 = 0, F 1 = 1, and n 2. Given a positive integer n, determine F n. Input: n 0 Output: F n 10 See Fibonacci numbers. Zheng-Liang Lu 220 / 227
Solution 1 function y = recursivefib(n) 2 if n == 0 3 y = 0; 4 elseif n == 1 5 y = 1; 6 else 7 y = recursivefib(n - 1) + recursivefib(n - 2); 8 end 9 end It is a binary recursion, because there are two calls in the function. Time complexity: O(2 n ) (Why?) Can we implement a linear recursion for this problem? Zheng-Liang Lu 221 / 227
Alternative: Linear Recursion 1 function ret = linearfib(n) 2 ret = fib(0, 1, n); 3 function c = fib(a, b, n) % nested function 4 if n > 0 5 c = fib(b, b + a, n - 1); 6 else 7 c = a; 8 end 9 end 10 end Time complexity: O(n)! You can implement a loop version of this problem. (Try.) Zheng-Liang Lu 222 / 227
Fibinacci Numbers by Loops 1 function y = loopfib(n) 2 if n == 0 3 y = 0; 4 elseif n == 1 5 y = 1; 6 else 7 x = 0; 8 y = 1; 9 for i = 2 : n 10 tmp = x + y; 11 x = y; 12 y = tmp; 13 end 14 end 15 end Zheng-Liang Lu 223 / 227
Remarks Recursion bears substantial overhead. So, the recursive algorithm may execute a bit more slowly than the iterative equivalent. 11 Besides, a deeply recursive method depletes the call stack, which is limited, and causes a exception fast. 12 In practice, the decision whether to use recursion or iteration should be based on the nature of, and your understanding of, the problem you are trying to solve. 11 In modern compiler design, recursion elimination is automatic if the recurrence occurs in the last statement in the recursive function, so called tail recursion. However, only some of programming languages support the elimination of tail recursion. Unfortunately, Matlab does not support it. 12 Stack overflow. Zheng-Liang Lu 224 / 227
More Interesting Recursions Sum of numbers Product of numbers Greatest common divisor Towers of Hanoi Binary search Check whether a string is palindrome 13 using recursion 13 For example, noon, level, and radar. Zheng-Liang Lu 225 / 227
Computational Thinking 14 To think about computing, we need to be attuned to three fields: science, technology, and society. Computational thinking shares with mathematical thinking: the way to solve problems engineering thinking: the way to design and evaluating a large, complex system scientific thinking: the way to understand computability, intelligence, the mind and human behavior. 14 You should read this: http://rsta.royalsocietypublishing.org/content/366/1881/3717.full Zheng-Liang Lu 226 / 227
The essence of computational thinking is abstraction. An algorithm is an abstraction of a step-by-step procedure for taking input and producing some desired output. A programming language is an abstraction of a set of strings each of which when interpreted effects some computation. And more. 15 The abstraction process - deciding what details we need to highlight and what details we can ignore - underlies computational thinking. The abstraction process also introduces layers. Well-defined interfaces between layers enable us to build large, complex systems. 15 For example, API and TCP/IP. Zheng-Liang Lu 227 / 227