| CSCI A201/A597 Lecture Notes Twelve
Second Summer 2000
|
Decisions
|
The programs we have seen so far are fairly inflexible.
|
Except for variations in the input they work the same way with every program run.
|
|
One of the essential features of nontrivial computer programs is the ability to make decisions...
|
... and to carry out different actions, depending on the nature of the inputs.
|
|
The goal of this chapter is to learn how to program simple and complex decisions.
|
Learning that will greatly increase our expressive power in Java.
|
|
In some of the previous assignments we went to great length to either fake decisions by
building them into clever formulas.
|
Let's implement the withdraw method so that you cannot withdraw more money that you have in your account.
|
That is, the withdraw method must make a decision: whether to allow the withdrawal or not.
|
The if statement is used to implement a decision.
It has two parts: a test and a body.
|
If the test succeeds, the body of the if statement is executed.
|
Here's an example, as a flowchart:
|
if (amount <= balance)
balance = balance - amount;
| |
The test is in red and the body of the
if statement is in blue.
|
A statement such as
balance -= amount;
is called a simple statement.
|
A conditional statement, such as:
if (x > 0) y = x;
is called a compound statement.
|
Our programs remain sequences of statements, we just allow
compound statements such as the if statements
in our programs.
|
Soon we will encounter, and start using, other compound statements: the
so-called loops.
|
To implement a real alternative, use the if/else statement:
|
... if the condition is satisfied then the first block is executed; otherwise
the second is executed.
|
| |
In Java, and with colors, that is:
|
if (amount <= balance)
balance = balance - amount;
else
balance = balance - OVERDRAFT_PENALTY;
Quite often the body of an if statement consists of multiple
statements that must be executed in sequence whenever the test is succesful.
|
These statements must be grouped together to form a block statement by
enclosing them in braces { }.
|
|
Here's a somewhat contrived example:
|
|
if (x < y) {
temp = x;
x = y;
y = temp;
}
| |
We assume, of course, that x, y, and
temp have been declared and that (at least as far as x and y
are concerned) they have been initialized already.
|
|
Can you briefly say what the code is doing?
|
It makes sure that of the two values the larger one is always in x.
|
|
Very good. What were we saying about braces?
|
They group statements together.
|
|
What if we drop them?
|
Then the code no longer works as intended.
|
So what is the syntax of an if statement? |
The body of an if statement (or an else alternative) must be
a statement (just one).
|
But it can be:
- a simple statement
- a compound statement (such as another
if statement), or
- a block statement
|
| |
It's good to get into the habit of using braces (and thus block statements) all the time.
|
|
Yes, as we will see when we get to exercises, shortly.
|
I can hardly wait. But first, let's analyze the
if statement closer, and look at what
makes a test.
|
Its outcome is either true or false.
|
In many cases the test compares two values.
|
Comparison operators such as <= are
called relational operators.
|
Java has six relational operators.
|
| Java | Math | Description |
> |
> | Greater thaqn |
>= |
| Greater than or equal |
< |
< | Less than |
<= |
| Less than or equal |
== |
= | Equal |
!= |
| Not equal |
The == operator is initially confusing to
most newcomers to Java.
|
In Java, the = symbol already has a meaning,
namely assignment.
|
The == denotes equality testing:
|
|
a = 5; // assign 5 to a
if (a == 3) // tests whether a equals 3
System.out.println("a is equal to 3");
else
System.out.println("a is not equal to 3");
| |
You will have to remember to use == for equality testing and
to use = for assignment.
|
|
Floating point numbers have only a limited precision, and
calculations can introduce roundoff errors.
|
That means we need to be careful when we want to test if two floating
point quantities are representing the same thing.
|
double r = Math.sqrt(2);
if (r * r == 2)
System.out.println(r * r + " == 2");
else
System.out.println(r * r + " != 2");
| |
Unfortunately such roundoff errors are unavoidable.
|
|
In most circumstances it does not make a lot of sense to
compare floating point numbers exactly.
|
Instead we should test whether they're close enough.
|
|
That is, the absolute value of their difference should be less than some threshold.
|
Mathematically, x and y are close enough if

|
... for a very small number, .
|
Greek letter epsilon is commonly used to denote a very small quantity.
|
It is common to set
to 10-14 when comparing double
numbers.
|
However, this is not always good enough.
|
|
Indeed, if the two numbers are very big, then one can be a
roundoff of the other even if their difference is much bigger
than 10-14.
|
To overcome this problem we need to normalize: we divide
by the magnitude of the numbers before comparing how close
they are.
|
So x and y are close enough if

|
And to avoid division by zero it is better to test whether

|
Math.abs(x - y) <= EPSILON * Math.max(Math.abs(x), Math.abs(y))
| |
OK, I think I understand how I test numbers for equality.
|
|
What else can we test for equality?
|
How about Strings?
|
|
To test whether two strings are equal to each other, ...
|
..., that is, that their contents is the same, ...
|
... one must use method equals.
|
Why not use == like for numbers?
|
Strings are objects.
|
And so are Rectangles.
|
If you compare two object references with the
== operator, ...
|
... you test whether the references
refer to the same object.
|
|
That's because you check to see whether the two locations contain the same thing.
|
Which is in each case an address, to an actual object.
|
Rectangle a = new Rectangle(5, 10, 20, 30);
Rectangle b = a;
Rectangle c = new Rectangle(5, 10, 20, 30);
| |
The comparison a == b is true.
|
|
Both object variables refer to the same object.
|
But the comparison a == c is false.
|
|
The two object variables refer to different objects.
| |

| |
It does not matter that the objects have identical contents.
|
You can use the equals method to test whether two rectangle have the same contents.
|
Thus a.equals(c) is true.
|
And so is c.equals(b) obviously.
|
Same with Strings, so we will have to remember to use equals for string comparison.
|
In Java letter case matters.
Thus "harry".equals("HARRY") evaluates to false.
|
But "harry".equalsIgnoreCase("HARRY") evaluates to true.
|
|
Even if two strings don't have "identical" contents
we may still want to know the relationship between them.
|
The compareTo method compares strings in dictionary order.
|
If string1.comparesTo(string2) < 0
|
... then string1 comes before string1 in dictionary order.
|
If string1.comparesTo(string2) > 0
|
... then string1 comes after string2 in dictionary order.
|
If string1.comparesTo(string2) == 0
|
... then the two strings have identical contents.
|
You should look this method up in class String.
|
Actually the dictionary ordering used by Java ius slightly different from that of a normal dictionary.
|
|
Java is case-sensitive and sorts characters
by listing numbers first, then uppercase characters, then lowercase characters.
|
For example 1 comes before B which comes before a.
|
|
And the space character comes before all other characters.
|
Can we describe the comparison process a little bit in greater detail?
|
|
When comparing two strings, corresponding letters are compared until one of the strings ends
or the first difference is encountered.
|
If one of the strings ends, the longer string is considered the later one.
|
|
If a character mismatch is found, compare the characters to determine which string comes later
in the dictionary sequence.
|
The process is called lexicographic comparison.
|
That's
why "car" comes before "cargo",
|
And "cathode" comes after "cargo" in lexicographic ordering.
|
| Time for a break. |
I sure think so.
|
|
And some exercises too.
|
Yes, but the break first, please.
|
Last updated: July 9, 2000 by Adrian German for A201