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
Object-Oriented Programming 95-712 MISM/MSIT Carnegie Mellon University Lecture 2: Program Control Today We Look At Java operators Control structures More example programs Java Operators An operator takes one or more “things” and produces a resultant “thing”. “Things” are usually primitive types, but they are sometimes objects. The “things” operated upon are called operands. An operator is just a function, but with a different syntax. A Familiar Example int i = 3, j = 4, k; k = i + j; The assignment operator and the addition operator are used (each exactly once!). This is a more familiar syntax than, e.g., k.equals(i.add(j)); More Operator Facts All operators produce a value. Sometimes they produce side effects, i.e., they change the value of an operand. Evaluation of a statement with several operators follows precedence rules. Use parentheses for readability. (x + y) * z / 3 is different than x + y * z / 3 Assignment Is Tricky, Part I public class Number { int i; } public class Assignment1 { public static void main(String[] args) { Number n1 = new Number(); Number n1 = new Number(); n1.i = 2; n2.i = 5; n1.i = n2.i; n2.i = 10; // what is n1.i? } } Assignment Is Tricky, Part II public class Assignment2 { public static void main(String[] args) { Number n1 = new Number(); Number n1 = new Number(); n1.i = 2; n2.i = 5; n1 = n2; n2.i = 10; // what is n1.i? n1.i = 20; // what is n2.i? } } A Picture Might Help Before assignment n1 = n2 Number objects reference variables n1 n2 n2.i 5 n1.i 2 After assignment n1 = n2 Number objects reference variables n1 n2 n2.i n1.i 5 2 “Aliasing” In Function Calls public class PassObject { static void f(Number m) { m.i = 15; } public static void main(String[] args) { Number n = new Number(); f(n); // what is n.i now? } } Math Operators +, -, *, /, % Integer division truncates, i.e., 16/3 = 5 Modulus operator returns remainder on integer division, i.e., 16%3 = 1 Shorthand: x += 4; is the same as x = x + 4; This works for the other math operators as well. Auto Increment and Decrement ++ increases by one, and -- decreases by one. Two flavors of each: pre and post: int i = 1, j; j = i++; j = ++i; j = i--; j = --i; // j = 1, i = 2 // j = 3, i = 3 // j = 3, i = 2 // j = 1, i = 1 Booleans and Relational Operators The boolean type has two possible values, true and false. The relational operators >, >=, <, <=, == and != produce a boolean result. >, >=, <, <= are legal for all built-in types except booleans, == and != are legal for all. Testing for (Non-)Equivalence The == and != operators need to be used with care with objects. public class Equivalence { public static void main(String[] args) { Integer n1 = new Integer(47); Integer n2 = new Integer(47); System.out.println(n1 == n2); // prints false System.put.println(n1 != n2); // prints true } } The equals( ) Operator This exists for all objects (don’t need it for built-in types). Integer n1 = new Integer(47); Integer n2 = new Integer(47); System.out.println(n1.equals(n2); // prints true The equals( ) Operator (cont.) But exists doesn’t necessarily mean properly defined! class Number { int i; } : Number n1 = new Number(); Number n2 = new Number(); n1.i = 3; n2.i = 3; System.out.println(n1.equals(n2)); // prints false The equals( ) Operator (cont.) The equals( ) operator is properly defined for most Java library classes. The default behavior is to compare references, so… When you define a class, if you’re planning to use equals( ), you need to define it (i.e., override the default behavior). Logical Operators These are AND (&&), OR (||), and NOT (!). These work on booleans only; if you have old “C” habits, forget them! Use parentheses freely to group logical expressions. Logical expressions short-circuit; as soon as the result is known, evaluation stops. Short-Circuiting Example public class ShortCircuit { static boolean test1(int val) {return val < 1;} static boolean test2(int val) {return val < 2;} static boolean test3(int val) {return val < 3;} public static void main(String[] args) { if (test1(0) && test2(2) && test3(2)) System.out.println(“Expression is true”); else System.out.println(“Expression is false”); } } Bitwise, Shift, Ternary Operators Bitwise & shift operators manipulate individual bits in integral primitive types. I almost never use them, except for masks, when memory is tight. YMMV The ternary if-else operator looks like this: boolean-expression ? value0 : value1 The result is either value0 or value1, depending on the truth of the boolean. The String + Operator The + operator is “overloaded” for String objects; it means concatenation. It reminds me of good old C++… If an expression begins with a String, then all the following operands of + will be converted into Strings: int x = 0, y = 1; z = 2; String myString = “x, y, z ”; System.out.println(myString + x + y + z); Casting A cast produces a temporary new value of a designated type. Implicit and explicit casts: int i = 2; float f = i; // OK, since f can hold all of i float g = 3.14159; //! int j = g; // not OK, loses information int k = (int) g; // OK, compiler is reassured Execution Control: if-else if (boolean_expression) statement else if(boolean_expression) statement : else if(boolean_expression) statement else statement if-else Example public int test(int testVal, int target) { int result = 0; if (testVal > target) result = +1; else if (testVal < target) result = -1; else { System.out.println(“They are equal”); result = 0; } return result; } Execution Control: return Exit a method, returning an actual value or object, or not (if the return type is void). public int test(int testVal, int target) { if (testVal > target) return = +1; else if (testVal < target) return = -1; else { System.out.println(“They are equal”); result = 0; } } Three Kinds of Iteration while (boolean_expression) // evaluate first statement_or_block do statement_or_block while (boolean_expression) // evaluate last for (initialization ; boolean_expression ; step) statement_or_block Example: for (int i = 0; i < myArray.size(); i++) { myArray[i] = 0; } public class BreakAndContinue { public static void main(String[] args) { for (int i = 0; i < 100; i++) { if (i == 74) break; // out of for loop if (i % 9 != 0) continue; // next iteration System.out.println(i); } int i = 0; // this does work while (true) { // an infinite loop i++; int j = i * 27; if (j == 1269) break; // out of loop if (i % 10 != 0) continue; // top of loop } } Selection Via switch for (int i = 0; i < 100; i++) { char c = (char) (Math.random() * 26 + ‘a’); switch(c) { case ‘a’: case ‘e’: case ‘i’: case ‘o’: case ‘u’: System.out.println(“Vowel”); break; case ‘y’: case ‘w’: System.out.println(“Sometimes a vowel”); break; default: System.out.println(“Not a vowel”); } Digression on Random Numbers Despite theory, most random number generators are more like “kids playing with matches”. – See “Random Number Generators: Good Ones Are Hard to Find” by S. Park and K. Miller, CACM Oct. 1988. Most random number generators use “multiplicative linear congruential” schemes: – A modulus m, a large prime integer – A multiplier a, an integer in the range 2,3,…m-1 – These produce a sequence z1, z2, z3… using the iterative equation – zi+1 = f(zi) = a*z % m Random Numbers (cont.) The sequence is initiated by choosing a seed. Example: f(z) = 6z %13. This produces the sequence ...1 , 6, 10, 8, 9, 2, 12, 7, 3, 5, 4, 11, 1,... Example: f(z) = 7z % 13. This produces the sequence ...1 , 7, 10, 5, 9, 11, 12, 6, 3, 8, 4, 2, 1,... Is the latter somehow "less random"? Example: f(z) = 5z %13. This produces the sequence ...1 , 5, 12, 8, 1... Examples of Rotten RNGs IBM's RANDU for SYSTEM/360: – f(z) = 65539z % 231. Not full period, dependent on results of overflow operations, low-order bits cycle w/ period 2! Prime’s Scheffield Pascal, an even worse version SAS Modula 2 Many LISPs and Prologs Hundreds of CS textbooks Turbo Pascal One generator had a fixed point! Using Java’s RNGs (cont.) java.lang.Math – static double random() random in [0, 1.0) The sequence doesn’t seem to be repeatable Bad for debugging Good for experimental work What’s a Seed? Here is a sequence I generated on Friday at 9:30, with the code: Random randomGenerator = new Random(); for (int i = 0; i < 10; i++) System.out.println(randomGenerator.nextInt()); -1321140701 i=0 1591074477 i=1 646222811 i=2 Random number i = 3 1633627825 sequence -2039264851 i=4 i=5 -315534709 What’s a Seed? I ran the same code again at 10:30, and got this: -403585738 i=0 -2092042741 i=1 -333693675 i=2 Random number i = 3 -331823022 sequence 1651689643 i=4 i=5 133526058 What’s a Seed? I ran this code at 10:35 Random randomGenerator = new Random(1234); for (int i = 0; i < 10; i++) System.out.println(randomGenerator.nextInt()); -1517918040 i=0 1115789266 i=1 -208917030 i=2 Random number i = 3 1019800440 sequence -6116528751 i=4 i=5 1362132786 What’s a Seed? I ran this code at 10:45 and got the same sequence. Random randomGenerator = new Random(1234); for (int i = 0; i < 10; i++) System.out.println(randomGenerator.nextInt()); -1517918040 i=0 1115789266 i=1 -208917030 i=2 Random number i = 3 1019800440 sequence -6116528751 i=4 i=5 1362132786 Using Java’s RNGs (cont.) java.util.Random – Constructors: » Random() » Random(long seed) – Methods: » » » » nextInt() nextInt(int n) nextFloat() setSeed(long seed) random in (-231, 231-1) random in [0, n) random in [0, 1) java.lang.Math – static double random() random in [0, 1.0) Random Numbers In Action: The Monte Hall Paradox Monte Hall hosts a TV game show, “Let’s Make a Deal”. One contestant is shown three doors. Behind one of the doors is a “Fabulous Grand Prize”. Behind the other two doors are “worthless prizes”. The Monte Hall Paradox The contestant selects a door. Monte opens a door not selected by the contestant, and this always shows a worthless prize. The contestant can choose to change her selection to the other door not opened by Monte Hall. Should the contestant change doors? The Monte Hall Paradox Very intelligent people are confused! – Any initial door choice has a 1/3 chance of winning. – Why would changing the door choice increase or decrease the odds of winning the “Fabulous Grand Prize”? – Can’t we settle this with a computer simulation? The Door Class public class Door { boolean open; boolean hasGrandPrize; boolean chosenByContestant; } The Game Class import java.util.*; public class Game { Door door1, door2, door3; void setUpGame() { door1 = new Door();door2 = new Door();door3 = new Door(); // initialize all the Door variables to false Random r = new Random(); int grandPrizeDoor = r.nextInt(3); switch(grandPrizeDoor) { case 0: door1.hasGrandPrize = true; break; case 1: // etc. } } Reality Check For Game Class void printStateOfDoors() { System.out.println("Door 1 is " + (door1.open ? " open, " : "not open, ") + (door1.hasGrandPrize ? "is the grand prize, and " : "is no (door1.chosenByContestant ? "is chosen." : "is not chosen System.out.println("Door 2 is " + (door2.open ? " open, " : "not open, ") + (door2.hasGrandPrize ? "is the grand prize, and " : "is no (door2.chosenByContestant ? "is chosen." : "is not chosen System.out.println("Door 3 is " + (door3.open ? " open, " : "not open, ") + (door3.hasGrandPrize ? "is the grand prize, and " : "is no (door3.chosenByContestant ? "is chosen." : "is not chosen } The Game Class public class Game { Door door1, door2, door3; void setUpGame() { // shown earlier} void contestantChooseDoor() { Random r = new Random(); int contestantDoor = r.nextInt(3); switch(contestantDoor) { case 0: door1.chosenByContestant = true; break; case 1: door2.chosenByContestant = true; break; case 2: door3.chosenByContestant = true; break; } } } The PlayManyGames Class public class PlayManyGames { public static void main(String[] args) { Game theGame = new Game(); theGame.setUpGame(); theGame.printStateOfDoors(); theGame.contestantChooseDoor(); theGame.printStateOfDoors(); } } A Problem: First Run Door 1 is not open, is not the grand prize, and is not chosen. Door 2 is not open, is not the grand prize, and is not chosen. Door 3 is not open, is the grand prize, and is not chosen. Door 1 is not open, is not the grand prize, and is not chosen. Door 2 is not open, is not the grand prize, and is not chosen. Door 3 is not open, is the grand prize, and is chosen. A Problem: Second Run Door 1 is not open, is not the grand prize, and is not chosen. Door 2 is not open, is the grand prize, and is not chosen. Door 3 is not open, is not the grand prize, and is not chosen. Door 1 is not open, is not the grand prize, and is not chosen. Door 2 is not open, is the grand prize, and is chosen. Door 3 is not open, is not the grand prize, and is not chosen. A Problem: Third Run Door 1 is not open, is the grand prize, and is not chosen. Door 2 is not open, is not the grand prize, and is not chosen. Door 3 is not open, is not the grand prize, and is not chosen. Door 1 is not open, is the grand prize, and is chosen. Door 2 is not open, is not the grand prize, and is not chosen. Door 3 is not open, is not the grand prize, and is not chosen. The Solution The RNGs in both methods of the Game class are starting from the same seed. Solution: Take the RNG out of the methods, and into the Game class itself. But each instance of the Game class will still start at the same place. Solution: Make the RNG a static variable. The New Game Class public class Game { Door door1, door2, door3; static Random r = new Random(); void setUpGame() { int grandPrizeDoor = r.nextInt(3); switch(grandPrizeDoor) { // etc. } void contestantChooseDoor() { int contestantDoor = r.nextInt(3); switch(contestantDoor) { // etc. } } Completing the Simulation Add Game methods for – Monte choosing a door to open – The player switching or not – Deciding if the player has won Add PlayManyGames code to – – – – Call the new Game methods Put everything in a loop Prompt the user for # of trials, switching policy Display the results