1 / 51

More work with functions

More work with functions. Recall the “diary encoding problem”:. (We shifted letters of the alphabet one position to the left.) So IBM becomes HAL . And Mary becomes Lzqx. Here’s the complete program that writes the encoded information to another file.

eithne
Télécharger la présentation

More work with functions

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. More work with functions

  2. Recall the “diary encoding problem”: • (We shifted letters of the alphabet one position to the left.) • So IBM becomes HAL. • And Mary becomes Lzqx.

  3. Here’s the complete program that writes the encoded information to another file. Can we make a function out of the encoding part? That would make our code more readable and modular (in case we want to change the encoding). import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.Scanner; class Encode { public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); //perform encoding char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } outLine = outLine + enc; } out.println( outLine ); //output encoded line } out.close(); in.close(); } }

  4. Java code segment for encoding: char enc; if (ch=='a') { //handle lowercase letters enc = 'z'; } else if (ch>'a' && ch<='z') { //handle lowercase letters enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { //handle uppercase letters enc = (char)(ch-1); } else { enc = ch; //unchanged }

  5. Recall the steps to define your own function. • Decide on a name for your function. • Determine what arguments your function needs to do its job. • Determine the return type of your function. • Code your function.

  6. Steps to define your own function. Step 1. Decide on a name. encode

  7. Steps to define your own function. Step 2. Determine what arguments your functions needs to do its job. • What does encode need to do its job? • One character to check/translate. char before

  8. After steps 1 and 2. encode ( char before ) { … } Step 3. What type of thing does our function return?

  9. After steps 1 and 2. encode ( char before ) { … } Step 3. What type of thing does our function return? the encoded char

  10. After steps 1, 2, and 3. static char encode ( char before ) { … } Now all we have to do is fill in the body of our function! The simplest encoder is one that doesn’t make any change. What should that encoder return?

  11. After steps 1, 2, and 3. static char encode ( char before ) { return before; } Now all we have to do is fill in the body of our function. The simplest encoder is one that doesn’t make any change. How can we use this simple encoder function?

  12. To use this simple encoder function, we first add it to our class (inside class definition but outside of main). … class Encode { static char encode ( char before ) { return before; } public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } outLine = outLine + enc; } out.println( outLine ); //output encoded line } ….

  13. To use this simple encoder function, we first add it to our class. The next step is to replace the encoding code in main with a call to our encode function. … class Encode { static char encode ( char before ) { return before; } public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } outLine = outLine + enc; } out.println( outLine ); //output encoded line } ….

  14. To use this simple encoder function, we first add it to our class. The next step is to replace the encoding code in main with a call to our encode function. What functions do we already call in main? … class Encode { static char encode ( char before ) { return before; } public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } outLine = outLine + enc; } out.println( outLine ); //output encoded line } ….

  15. To use this simple encoder function, we first add it to our class. The next step is to replace the encoding code in main with a call to our encode function. We already call these functions in main! … class Encode { static char encode ( char before ) { return before; } public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } outLine = outLine + enc; } out.println( outLine ); //output encoded line } ….

  16. So we replace all this with what? … class Encode { static char encode ( char before ) { return before; } public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged } outLine = outLine + enc; } out.println( outLine ); //output encoded line } ….

  17. class Encode { static char encode ( char before ) { return before; } public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); char enc = encode( ch ); outLine = outLine + encode( ch ); outLine = outLine + enc; } out.println( outLine ); //output encoded line } …. Both versions are fine.

  18. class Encode { static char encode ( char before ) { return before; } public static void main ( String args[] ) throws Exception { //open the input file Scanner in = new Scanner( new FileInputStream("diary.txt") ); //open the output file PrintWriter out = new PrintWriter( new FileOutputStream("out.txt") ); //read & write one line at a time while ( in.hasNextLine() ) { String s = in.nextLine(); String outLine = ""; System.out.println( "read: " + s ); for (int i=0; i<s.length(); i++) { char ch = s.charAt( i ); outLine += encode( s.charAt(i) ); outLine = outLine + encode( ch ); } out.println( outLine ); //output encoded line } …. This is OK as well.

  19. class Encode { static char encode ( char before ) { return before; } …. Now we need to complete the encode function based on our code from before: char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged }

  20. class Encode { static char encode ( char before ) { return before; } …. Note that ch below is called before w/in the scope of the encode function. Also for readability, since ch is before, let’s call encafter. char enc; if (ch=='a') { enc = 'z'; } else if (ch>'a' && ch<='z') { enc = (char)(ch-1); } else if (ch=='A') { //handle uppercase letters enc = 'Z'; } else if (ch>'A' && ch<='Z') { enc = (char)(ch-1); } else { enc = ch; //unchanged }

  21. Our completed encode function … class Encode { //encode a given character for our secret code static char encode ( char before ) { char after; if (before=='a') { after = 'z'; } else if (before>'a' && before<='z') { after = (char)(before-1); } else if (before=='A') { //handle uppercase letters after = 'Z'; } else if (before>'A' && before<='Z') { after = (char)(before-1); } else { after = before; //unchanged } return after; } ….

  22. Our completed encode function … class Encode { //encode a given character for our secret code static char encode ( char before ) { char after = before; //unchanged if (before=='a') { after = 'z'; } else if (before>'a' && before<='z') { after = (char)(before-1); } else if (before=='A') { //handle uppercase letters after = 'Z'; } else if (before>'A' && before<='Z') { after = (char)(before-1); } else { after = before; //unchanged } return after; } …. a slightly different way

  23. Our completed encode function … class Encode { //encode a given character for our secret code static char encode ( char before ) { if (before=='a') { return ‘z‘; } else if (before>'a' && before<='z') { return (char)(before-1); } else if (before=='A') { //handle uppercase letters return 'Z'; } else if (before>'A' && before<='Z') { return (char)(before-1); } return before; //unchanged } …. a slightly different way

  24. A function that approximates sine

  25. A function to approximate sine • From http://en.wikipedia.org/wiki/Trigonometric_function#Series_definitions

  26. The sine function (blue) is closely approximated by its Taylor polynomial of degree 7 (pink) for a full cycle centered on the origin.

  27. Let’s write a function to approximate sine • Use the following polynomial:

  28. Recall the steps to define your own function. • Decide on a name for your function. • Determine what arguments your function needs to do its job. • Determine the return type of your function. • Code your function.

  29. Steps 1 • Decide on a name for your function. almostSine

  30. Steps 2 • Determine what arguments your function needs to do its job. almostSine ( double x )

  31. Steps 3 • Determine the return type of your function. static double almostSine ( double x )

  32. Steps 4 • Code your function. //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { }

  33. Steps 4 • Code your function. //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = ?; double x7 = ?; double y = ?; return y; } Note: A loop over the number of terms is more general, but for simplicity we will use only 4 terms.

  34. Steps 4 • Code your function. //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = ?; double fact5 = ?; double fact7 = ?; double y = ?; return y; }

  35. Steps 4 • Code your function. //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = 3 * 2; double fact5 = 5 * 4 * fact3; double fact7 = 7 * 6 * fact5; double y = ?; return y; }

  36. Steps 4 • Code your function. //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = 3 * 2; double fact5 = 5 * 4 * fact3; double fact7 = 7 * 6 * fact5; double y = x – x3/fact3 + x5/fact5 – x7/fact7; return y; }

  37. class MySine { //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = 3 * 2; double fact5 = 5 * 4 * fact3; double fact7 = 7 * 6 * fact5; double y = x - x3/fact3 + x5/fact5 - x7/fact7; return y; } How can we test our new function, almostSine?

  38. class MySine { //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = 3 * 2; double fact5 = 5 * 4 * fact3; double fact7 = 7 * 6 * fact5; double y = x - x3/fact3 + x5/fact5 - x7/fact7; return y; } public static void main ( String args[] ) { for (double d=-2*Math.PI; d<=2*Math.PI; d+=Math.PI/2) { System.out.println( d + "\t" + Math.sin(d) ); } } } What does this print out? How can we modify it to print out the values of our new function as well?

  39. class MySine { //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = 3 * 2; double fact5 = 5 * 4 * fact3; double fact7 = 7 * 6 * fact5; double y = x - x3/fact3 + x5/fact5 - x7/fact7; return y; } public static void main ( String args[] ) { for (double d=-2*Math.PI; d<=2*Math.PI; d+=Math.PI/2) { System.out.println( d + "\t" + Math.sin(d) + "\t" + almostSine(d) ); } } }

  40. -12.566370614359172 4.898587196589413E-16 7525.149318866292 -10.995574287564276 1.0 2726.801987700507 -9.42477796076938 -3.6739403974420594E-16 821.0051310349569 -7.853981633974483 -1.0 189.61411535680668 -6.283185307179586 2.4492935982947064E-16 30.1591274102065 -4.71238898038469 1.0 3.602329768407337 -3.141592653589793 -1.2246467991473532E-16 0.0752206159036235 -1.5707963267948966 -1.0 -0.9998431013994987 0.0 0.0 0.0 1.5707963267948966 1.0 0.9998431013994987 3.141592653589793 1.2246467991473532E-16 -0.0752206159036235 4.71238898038469 -1.0 -3.602329768407337 6.283185307179586 -2.4492935982947064E-16 -30.1591274102065 7.853981633974483 1.0 -189.61411535680668 9.42477796076938 3.6739403974420594E-16 -821.0051310349569 10.995574287564276 -1.0 -2726.801987700507 12.566370614359172 -4.898587196589413E-16 -7525.149318866292 class MySine { //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = 3 * 2; double fact5 = 5 * 4 * fact3; double fact7 = 7 * 6 * fact5; double y = x - x3/fact3 + x5/fact5 - x7/fact7; return y; } public static void main ( String args[] ) { for (double d=-2*Math.PI; d<=2*Math.PI; d+=Math.PI/2) { System.out.println( d + "\t" + Math.sin(d) + "\t" + almostSine(d) ); } } } Can we format this better?

  41. -12.57 0.00 7525.15 -11.00 1.00 2726.80 -9.42 -0.00 821.01 -7.85 -1.00 189.61 -6.28 0.00 30.16 -4.71 1.00 3.60 -3.14 -0.00 0.08 -1.57 -1.00 -1.00 0.00 0.00 0.00 1.57 1.00 1.00 3.14 0.00 -0.08 4.71 -1.00 -3.60 6.28 -0.00 -30.16 7.85 1.00 -189.61 9.42 0.00 -821.01 11.00 -1.00 -2726.80 12.57 -0.00 -7525.15 It’s nice and readable now. And the values are good from –Pi to +Pi. But something happens here… class MySine { //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = 3 * 2; double fact5 = 5 * 4 * fact3; double fact7 = 7 * 6 * fact5; double y = x - x3/fact3 + x5/fact5 - x7/fact7; return y; } public static void main ( String args[] ) { for (double d=-Math.PI; d<=2*Math.PI; d+=Math.PI/2) { System.out.printf( "%8.2f %8.2f %8.2f \n", d, Math.sin(d), almostSine(d) ); } } }

  42. The sine function (blue) is closely approximated by its Taylor polynomial of degree 7 (pink) for a full cycle centered on the origin. Note what happens to our approximation outside of [-Pi,+Pi].

  43. So we need another function, f(x), which between –Pi and +Pi is x. • Outside of this range, we need to map each 2Pi interval to start at –Pi. • Then we could use almostSine(f(x)) and get a reasonable value.

  44. class MySine { //approx sine w/ a 7th degree polynomial static double almostSine ( double x ) { double x3 = x * x * x; double x5 = x3 * x * x; double x7 = x5 * x * x; double fact3 = 3 * 2; double fact5 = 5 * 4 * fact3; double fact7 = 7 * 6 * fact5; double y = x - x3/fact3 + x5/fact5 - x7/fact7; return y; } public static void main ( String args[] ) { for (double d=-Math.PI; d<=2*Math.PI; d+=Math.PI/2) { System.out.printf( "%8.2f %8.2f %8.2f \n", d, Math.sin(d), almostSine(f(d)) ); } } }

  45. So we need another function, f(x), which between –Pi and +Pi is x. • Outside of this range, we need to map each 2Pi interval to start at –Pi. • So let’s start with the identity function: static double f ( double x ) { return x; }

  46. So we need another function, f(x), which between –Pi and +Pi is x. • Outside of this range, we need to map each 2Pi interval to start at –Pi. static double f ( double x ) { //no change if in [-Pi..+Pi] if (-Math.PI<=x && x<=Math.PI) return x; return x; } How can we map each 2Pi interval to start at –Pi? (Did we use any arithmetic operator before that does this – random numbers and rolling dice?)

  47. So we need another function, f(x), which between –Pi and +Pi is x. • Outside of this range, we need to map each 2Pi interval to start at –Pi. static double f ( double x ) { //no change if in [-Pi..+Pi] if (-Math.PI<=x && x<=Math.PI) return x; x %= 2*Math.PI; return x; } If this yields a number in [-Pi..+Pi], then this is fine.

  48. So we need another function, f(x), which between –Pi and +Pi is x. • Outside of this range, we need to map each 2Pi interval to start at –Pi. static double f ( double x ) { //no change if in [-Pi..+Pi] if (-Math.PI<=x && x<=Math.PI) return x; x %= 2*Math.PI; if (-Math.PI<=x && x<=Math.PI) return x; return x; } If this yields a number in [-Pi..+Pi], then this is fine. Otherwise, we need to shift the result.

  49. So we need another function, f(x), which between –Pi and +Pi is x. • Outside of this range, we need to map each 2Pi interval to start at –Pi. static double f ( double x ) { //no change if in [-Pi..+Pi] if (-Math.PI<=x && x<=Math.PI) return x; x %= 2*Math.PI; if (-Math.PI<=x && x<=Math.PI) return x; if (x>0) return x - 2*Math.PI; return x; } If this yields a number in [-Pi..+Pi], then this is fine. Otherwise, we need to shift the result.

  50. So we need another function, f(x), which between –Pi and +Pi is x. • Outside of this range, we need to map each 2Pi interval to start at –Pi. static double f ( double x ) { //no change if in [-Pi..+Pi] if (-Math.PI<=x && x<=Math.PI) return x; x %= 2*Math.PI; if (-Math.PI<=x && x<=Math.PI) return x; if (x>0) return x - 2*Math.PI; return x + 2*Math.PI; } If this yields a number in [-Pi..+Pi], then this is fine. Otherwise, we need to shift the result.

More Related