Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of 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