Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Functions: The first step in modularity Prof. Dionne Aleman MIE250: Fundamentals of object-oriented programming University of Toronto MIE250: Fundamentals of object-oriented programming (Aleman) Functions 1/1 Functions 2/1 Java program structure The .java file Header files The class Function Function Function MIE250: Fundamentals of object-oriented programming (Aleman) Why functions? I Reduce complexity I Facilitate understanding and modification I Help testing and debugging I Promote reusability MIE250: Fundamentals of object-oriented programming (Aleman) Functions 3/1 Factorial example 1 import java . io .*; 2 3 public class FactorialFn { 4 public static void main ( String [] args ) throws IOException , NumberFormatException { int n , k , nfact ; BufferedReader cin = new BufferedReader ( new InputStreamReader ( System . in )) ; do { System . out . print ( " Enter n (0 to quit ): ") ; n = Integer . parseInt ( cin . readLine () ) ; if ( n < 0) { System . out . println ( " Invalid value . Try again .\ n" ); } else if ( n > 0) { nfact = 1; for ( k = 2; k <= n ; k ++) nfact *= k ; System . out . println ( n + " ! = " + nfact + "\ n" ) ; } } while ( n != 0) ; } // end main 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 } src/FactorialFn.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 4/1 Factorial example I Even though calculating n! takes only a few lines, it’s not an interesting part of the program. I Those few lines distract us from the overall program flow (think human factors). I So, let’s move them into a function. MIE250: Fundamentals of object-oriented programming (Aleman) Functions 5/1 Factorial v2: Getting better 1 import java . io .*; 2 3 public class FactorialFnV2 { 4 public static void main ( String [] args ) throws IOException , NumberFormatException { int n , k , nfact ; BufferedReader cin = new BufferedReader ( new InputStreamReader ( System . in )) ; do { System . out . print ( " Enter n (0 to quit ): ") ; n = Integer . parseInt ( cin . readLine () ) ; if ( n < 0) { System . out . println ( " Invalid value . Try again .\ n" ); } else if ( n > 0) { System . out . println ( n + " ! = " + factorial ( n) + "\ n" ); } } while ( n != 0) ; } // end main 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // calculate factorial public static int factorial ( int f) { int nfact = 1; for ( int k = 2; k <= f ; k ++) nfact *= k ; return nfact ; } // end factorial 20 21 22 23 24 25 26 27 } src/FactorialFnV2.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 6/1 Some interesting points I The function call is in a print statement. Why is that allowed? I I n is passed into the function, but is called f inside the function. Does that matter? I I I Because the function returns an int and we can put an int in a print statement. Nope. The function call is only passing the value of n to the function, and the function can assign any name(s) it wants to the incoming value(s). Java is exclusively pass-by-value. There is no pass-by-reference! If f is changed inside the function, will it affect n in the main function? I I Nope. What happens in functions stays in functions. (exception: arrays) “Scope”: Where a variable exists MIE250: Fundamentals of object-oriented programming (Aleman) Functions 7/1 Functions 8/1 Break it down 1 2 3 4 5 6 public static int factorial ( int f ) { int nfact = 1; for ( int k = 2; k <= f ; k ++) nfact *= k; return nfact ; } src/partial/factorialfn.txt MIE250: Fundamentals of object-oriented programming (Aleman) Function construction 1 2 3 4 public static return_type fn_name ( arg_type arg_name [ ,...]) { // function_body return ???; // no return statement for void functions } I Return types: Any variable or object type or void I void functions don’t return anything MIE250: Fundamentals of object-oriented programming (Aleman) Functions 9/1 Add absolute value of numbers 1 import java . io .*; 2 3 public class AddAbsValFn { 4 public static void main ( String [] args ) throws IOException , NumberFormatException { double x , y , absSum ; BufferedReader cin = new BufferedReader ( new InputStreamReader ( System . in )); 5 6 7 8 System . out . print ( " Enter two numbers : " ) ; x = Double . parseDouble ( cin . readLine () ) ; y = Double . parseDouble ( cin . readLine () ) ; 9 10 11 12 absSum = addAbsVal (x , y ) ; 13 14 System . out . format ( " |%.2 f | + |%.2 f | = %.2 f \ n " , x , y , absSum ); 15 16 } // end main 17 18 // return sum of absolute values of two individual numbers public static double addAbsVal ( double x , double y ) { return Math . abs (x ) + Math . abs ( y ) ; } 19 20 21 22 23 } src/AddAbsValFn.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 10 / 1 Printing the menu 1 import java . io .*; 2 3 public class PrintMenuFn { 4 public static void main ( String [] args ) throws IOException , NumberFormatException { int choice ; BufferedReader cin = new BufferedReader ( new InputStreamReader ( System . in )) ; do { printMenu () ; choice = Integer . parseInt ( cin . readLine () ); 5 6 7 8 9 10 11 if ( choice == 1) { // do things } else if ( choice == 2) { // do other things } else if ( choice != 0) { System . out . println ( " ERROR : Invalid menu choice !\ n" ); } } while ( choice != 0) ; } // end main 12 13 14 15 16 17 18 19 20 21 22 23 // print the menu public static void printMenu () { System . out . println ( " MY JAVA PROGRAM ") ; System . out . println ( " 0 - Quit " ); System . out . println ( " 1 - Option 1" ); System . out . println ( " 2 - Option 2" ); System . out . print ( " \ nEnter choice : " ); } 24 25 26 27 28 29 30 31 32 } src/PrintMenuFn.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 11 / 1 Functions 12 / 1 Are these statements allowable? 1 2 System . out . println ( printMenu () ) ; int x = printMenu () ; MIE250: Fundamentals of object-oriented programming (Aleman) Odd, prime, or both? 1 public class OddPrime { 2 public static void main ( String [] args ) { String odd = " " , prime = " " ; System . out . println ( " No . Odd Prime " ); System . out . println ( " -----------------") ; for ( int i = 0; i < 1000; i ++) { if ( isOdd ( i ) ) odd = " X " ; else odd = " " ; 3 4 5 6 7 8 9 10 if ( isPrime ( i ) ) prime = " X" ; else prime = " " ; 11 12 13 System . out . format ( " %3 d %7 s %7 s \n " , i , odd , prime ) ; } // end loop over integers } // end main 14 15 16 17 // determine if an integer is prime public static boolean isPrime ( int n ) { for ( int i = 2; i <= n -1; i ++) { if ( n % i == 0) return false ; } return true ; } // end isPrime 18 19 20 21 22 23 24 25 26 // determine if an integer is odd public static boolean isOdd ( int n) { if (( n % 2) == 1) return true ; else return false ; } // end isOdd 27 28 29 30 31 32 } src/OddPrime.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 13 / 1 Ternary operators Say a lot with very little. 1 variable = ( logical_test ) ? value_if_true : value_if_false ; Parentheses () are optional, but usually help with clarity. MIE250: Fundamentals of object-oriented programming (Aleman) Functions 14 / 1 Odd, prime, or both? Condensed with ternary operator 1 public class OddPrimeV2 { 2 public static void main ( String [] args ) { System . out . println ( " No . Odd Prime " ); System . out . println ( " -----------------") ; for ( int i = 0; i < 1000; i ++) { String odd = isOdd ( i ) ? " X " : " " ; String prime = isPrime ( i ) ? "X " : " "; System . out . format ( " %3 d %7 s %7 s \n " , i , odd , prime ) ; } // end loop over integers } // end main 3 4 5 6 7 8 9 10 11 12 // determine if an integer is prime public static boolean isPrime ( int n ) { for ( int i = 2; i <= n -1; i ++) { if ( n % i == 0) return false ; } return true ; } // end isPrime 13 14 15 16 17 18 19 20 21 // determine if an integer is odd public static boolean isOdd ( int n) { if (( n % 2) == 1) return true ; else return false ; } // end isOdd 22 23 24 25 26 27 } src/OddPrimeV2.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 15 / 1 Transform a numerical score into a letter 1 import java . io .*; 2 3 public class LetterGradeFn { 4 public static void main ( String [] args ) throws IOException , NumberFormatException { double num ; char letter ; BufferedReader cin = new BufferedReader ( new InputStreamReader ( System . in )); 5 6 7 8 9 System . out . print (" Enter numerical grade : " ) ; num = Double . parseDouble ( cin . readLine () ) ; 10 11 12 letter = getLetterGrade ( num ) ; 13 14 System . out . format ( " %.2 f -> % s \ n " , num , letter ) ; 15 16 } // end main 17 18 // transform a numerical score into a letter grade public static char getLetterGrade ( double score ) { if ( score < 50) return ’F ’; if ( score < 60) return ’D ’; if ( score < 70) return ’C ’; if ( score < 80) return ’B ’; else return ’A ’; } 19 20 21 22 23 24 25 26 27 } src/LetterGradeFn.java Efficiency 1 2 3 4 5 6 char grade = ’F ’; if ( score < 50) grade if ( score < 60) grade if ( score < 70) grade if ( score < 80) grade else grade = ’A ’; = = = = ’F ’; ’D ’; ’C ’; ’B ’; 7 8 return grade ; Can you think of a more efficient method of implementing getLetterGrade()? I I will be sad if you say no. MIE250: Fundamentals of object-oriented programming (Aleman) Functions 17 / 1 Alternatives Alternative 1: 1 2 3 4 5 if ( score >= 90) grade = ’A ’; else if ( score >= 80 && score < 90) grade = ’B ’; else if ( score >= 70 && score < 80) grade = ’C ’; else if ( score >= 60 && score < 70) grade = ’D ’; else grade = ’F ’; Alternative 2: 1 2 3 4 5 if ( score >= 90) grade = ’A ’; else if ( score >= 80) grade = ’B ’; else if ( score >= 70) grade = ’C ’; else if ( score >= 60) grade = ’D ’; else grade = ’F ’; MIE250: Fundamentals of object-oriented programming (Aleman) Functions 18 / 1 Alternatives Alternative 3: 1 2 3 4 5 grade = ’F ’; if ( score >= if ( score >= if ( score >= if ( score >= 60) 70) 80) 90) grade grade grade grade = = = = ’D ’; ’C ’; ’B ’; ’A ’; grade grade grade grade = = = = ’A ’; ’B ’; ’C ’; ’D ’; Alternative 4: 1 2 3 4 5 if ( score >= if ( score >= if ( score >= if ( score >= grade = ’F ’; 90) 80) 70) 60) MIE250: Fundamentals of object-oriented programming (Aleman) Functions 19 / 1 Which implementations are most efficient? 1 public class PermComb { 2 3 4 5 6 public static void main ( String [] args ) { System . out . println ( " 10 P 3 = " + permutation (10 , 3) ) ; System . out . println ( " 10 C 3 = " + combination (10 , 3) ) ; } // end of main function 7 8 9 10 11 // permutation n P r : n ! / (n - r) ! public static int permutation ( int n , int r ) { return factorial ( n ) / factorial (n -r ) ; } 12 13 14 15 16 17 public static int permutationV2 ( int n , int r ) { int perm = 1; for ( int i = n - r +1; i <= n ; i ++) perm *= i ; return perm ; } 18 19 20 21 22 // combination n C r : n ! / ( r !( n - r) !) public static int combination ( int n , int r) { return factorial ( n ) / ( factorial (r ) * factorial (n -r ) ); } 23 24 25 26 27 28 public static int combinationV2 ( int n , int r ) { int comb = permutationV2 (n , r) ; for ( int i = 2; i <= r ; i ++) comb /= i ; return comb ; } 29 30 31 32 33 34 35 public static int factorial ( int f ) { int nfact = 1; for ( int k = 2; k <= f ; k ++) nfact *= k ; return nfact ; } } // end of class src/PermComb.java What happens to the vals array in the main function? 1 public class ArrayFn { 2 3 4 5 6 7 8 public static void main ( String [] args ) { int [] vals = {1 , 3 , 5 , 7 , 9}; printArray ( vals ) ; squareArray ( vals ) ; printArray ( vals ) ; } // end of main function 9 10 11 12 13 14 // square individual array elements public static void squareArray ( int [] x ) { for ( int i = 0; i < x . length ; i ++) x [i] *= x[ i ]; } 15 16 17 18 19 20 21 // print each element in an array public static void printArray ( int [] x ) { for ( int i = 0; i < x . length ; i ++) System . out . println ( i + " . " + x [ i ]) ; } } // end of class src/ArrayFn.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 21 / 1 How about now? 1 public class ArrayFnV2 { 2 public static void main ( String [] args ) { int [] vals = {1 , 3 , 5 , 7 , 9}; int [] valsSq = squareArray ( vals ) ; printArray ( vals ) ; printArray ( valsSq ) ; } // end of main function 3 4 5 6 7 8 9 // square individual array elements public static int [] squareArray ( int [] x ) { int [] sq = new int [ x . length ]; for ( int i = 0; i < x . length ; i ++) sq [i ] = x[ i ]* x [i ]; return sq ; } 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // print each element in an array public static void printArray ( int [] x ) { for ( int i = 0; i < x . length ; i ++) System . out . println ( i + " . " + x [ i ]) ; } } // end of class src/ArrayFnV2.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 22 / 1 What is the output of this program? 1 public class Functions { 2 public static void main ( String [] args ) { int i = 1, j = 2 , k = 3 , m ; X (i , j ); System . out . println ( ( i ++) + " " + (++ j ) ); m = i + 2; k = Y(m , j ) ; System . out . println ( i + " " + j) ; System . out . println ( Y (j , k +3) ) ; System . out . println ( i + " " + j + " " + k ); } 3 4 5 6 7 8 9 10 11 12 13 public static void X ( int a , int b) { int c = b; b = a; a = c; } 14 15 16 17 18 19 public static int Y ( int d , int e ) { d ++; e += 2; return Z (d ) + Z ( e ) ; } 20 21 22 23 24 25 27 public static int Z ( int f ) { return f / 2; 28 } 26 29 } src/Functions.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 23 / 1 Thinking about the user of your functions 1 import java . io .*; 2 3 public class AddAbsValFn { 4 public static void main ( String [] args ) throws IOException , NumberFormatException { double x , y , absSum ; BufferedReader cin = new BufferedReader ( new InputStreamReader ( System . in )) ; 5 6 7 8 System . out . print ( " Enter two numbers : ") ; x = Double . parseDouble ( cin . readLine () ); y = Double . parseDouble ( cin . readLine () ); 9 10 11 12 absSum = addAbsVal (x , y ) ; 13 14 System . out . format ( " |%.2 f | + |%.2 f| = %.2 f\ n" , x , y , absSum ); 15 16 } // end main 17 18 // return sum of absolute values of two individual numbers public static double addAbsVal ( double x , double y) { return Math . abs ( x ) + Math . abs ( y ); } 19 20 21 22 23 } src/AddAbsValFn.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 24 / 1 Overloading: Flexible function use I We can only use this function for one thing: adding two doubles I But what if we wanted to add several double values? Or ints? I I We could write new functions, e.g., addAbsValDbl3() (add three doubles), addAbsValInt5() (add five ints) But this quickly becomes impractical, and difficult for the you (the programmer) to remember. Overloading Function overloading refers to having functions with the same name, but different arguments. MIE250: Fundamentals of object-oriented programming (Aleman) Functions 25 / 1 Thinking about the user of your functions 1 import java . io .*; 2 3 public class AddAbsValFnV2 { 4 public static void main ( String [] args ) throws IOException , NumberFormatException { double x , y , absSum ; BufferedReader cin = new BufferedReader ( new InputStreamReader ( System . in ) ) ; 5 6 7 8 System . out . print ( " Enter two numbers : " ); x = Double . parseDouble ( cin . readLine () ) ; y = Double . parseDouble ( cin . readLine () ) ; absSum = addAbsVal (x , y ) ; System . out . format ( " |%.2 f | + |%.2 f | = %.2 f \n \ n" , x , y , absSum ) ; 9 10 11 12 13 14 System . out . print ( " Enter number of values in array : ") ; int n = Integer . parseInt ( cin . readLine () ) ; System . out . print ( " Enter all " + n + " values in array : " ); double [] z = new double [ n ]; for ( int i = 0; i < n ; i ++) z [ i ] = Double . parseDouble ( cin . readLine () ) ; absSum = addAbsVal ( z ) ; System . out . format ( " Sum of absolute values of array elements = %.2 f\ n" , absSum ) ; 15 16 17 18 19 20 21 22 23 } // end main 24 25 // return sum of absolute values of two individual numbers public static double addAbsVal ( double x , double y ) { return Math . abs ( x ) + Math . abs ( y) ; } 26 27 28 29 30 // return sum of absolute values of array elements public static double addAbsVal ( double [] x ) { double sum = 0.; for ( int i = 0; i < x . length ; i ++) sum += Math . abs ( x [ i ]) ; return sum ; } 31 32 33 34 35 36 37 38 } src/AddAbsValFnV2.java We can make as many varieties as we want For example, think about all the different ways we can use Math.pow(x,y) MIE250: Fundamentals of object-oriented programming (Aleman) Functions 27 / 1 Lucky Sevens gambling game: Let’s build it from scratch1 Roll two dice. If the values sum to 7, win $4, otherwise lose $1. 1A completed version is in src/LuckySevens_Complete.java MIE250: Fundamentals of object-oriented programming (Aleman) Functions 28 / 1 Before programming: Identify inputs and outputs Inputs I Starting money Outputs I Number of rolls until you have no more money I Peak winnings MIE250: Fundamentals of object-oriented programming (Aleman) Functions 29 / 1 Before programming: Determine program flow Increase cash by $4 yes yes Get starting cash value from user Roll dice Dice value = 7? Money left? no Quit no Decrease cash by $1 MIE250: Fundamentals of object-oriented programming (Aleman) Functions 30 / 1 Time to program Now that we know what we want to do, let’s build the program. MIE250: Fundamentals of object-oriented programming (Aleman) Functions 31 / 1 Simulation: An IE staple I What is the average peak winnings as a percentage of starting cash value? I What is the probability of lasting longer than n rolls with a certain starting cash value? I What starting cash value has the best dollars to rolls ratio? Simulation Due to uncertain outcomes, we can’t answer most questions like this with just one run of the game. We need to simulate many games in order to create a distribution of outcomes that we can analyze. MIE250: Fundamentals of object-oriented programming (Aleman) Functions 32 / 1 New Lucky Sevens simulation program flow Increase cash by $4 yes Get starting cash value from user Get # simulations from user Set simulation counter n = 0 Roll dice yes Dice value = 7? Money left? no Quit game no Collect stats Decrease cash by $1 Reset stats Set cash = starting cash Set n = n+1 no n =# simulations? yes Quit MIE250: Fundamentals of object-oriented programming (Aleman) Functions Do analysis 33 / 1 A skeleton of the program 1 2 3 4 5 public LuckySevensSimulation { public static void main ( String args []) { int cash = getStartingCash () ; int nRolls = 0; int maxCash = 0; 6 for ( int i = 0; i < 1000; i ++) { nRolls = play ( cash ) ; // or maybe maxCash = play ( cash ); // collect some stats on nRolls and maxCash ... } 7 8 9 10 11 // print out all stats results ... 12 } 13 14 // play the Lucky Sevens game public static int play ( int cash ) { ... } 15 16 17 // get starting cash amount from user public static int getStartingCash () { ... } 18 19 20 } MIE250: Fundamentals of object-oriented programming (Aleman) Functions 34 / 1 Bigger issues than just more loops ... I We want to collect at least two types of stats from each game: nRolls and maxCash. I But how do we get the play() function to return two values? I Answer: We can’t. Passing around lots of data There’s no pass-by-reference, so there is only one reasonable option: Create an object to store the data and then pass the one object around, or just have the object do all the work. Finally, let’s do some object-oriented programming! MIE250: Fundamentals of object-oriented programming (Aleman) Functions 35 / 1