Spring Semester 2002 |
if
statements.
After each statement we list the correct version annotated in blue.
Condition must be enclosed in parens, and there is noif quarters > 0 then System.out.println(quarters + "quarters"); if (quarters > 0)thenSystem.out.println(quarters + "quarters");
then
keyword in Java.
Condition must be enclosed in parens, and one parenthesis was missing.if (1 + x > Math.pow(x, Math.sqrt(2)) y = y + x; if (1 + x > Math.pow(x, Math.sqrt(2))) y = y + x;
We should always remember to useif (x = 1) y++; else if (x = 2) y = y + 2; if (x == 1) y++; else if (x == 2) y = y + 2;
==
to test for equality
as =
is used exclusively for assignment.
Presumably we want the condition to mean "both x and y are zero". But in that case we need to write a syntactically correct expression in which we refer to each variable in part: "(x is zero) and (y is zero)". The fact that later x is used as a coordinate eliminates all doubts that x might actually be a boolean variable (in which case the condition, as written originally, was correct).if (x && y == 0) p = new Point2D.Double(x, y); if (x == 0 && y == 0) p = new Point2D.Double(x, y);
Just like in the previous exercise we need to properly assemble a boolean expression by putting together something that reads as follows: "(x is greater than or equal to 1) and (x is smaller than or equal to 10)"if (1 <= x <= 10) { System.out.println("Enter y:"); y = console.readDouble(); } if (1 <= x && x <= 10) { System.out.println("Enter y:"); y = console.readDouble(); }
Remember to useif (s != "nickels" || s != "pennies" || s != "dimes" || s != "quarters") System.out.print("Input error!"); if ( !s.equals("nickels" ) && !s.equals("pennies" ) && !s.equals("dimes" ) && !s.equals("quarters") ) System.out.print("Input error!");
equals
when comparing String
s.
(!=
is the negation of ==
).
Also, overall the code was supposed to implement an input error detection
mechanism. If you think carefully about it, the error message should only appear
if s
is not "nickels"
and s
is not "pennies"
and s
is not "dimes"
and s
is not "quarters"
.
So that was another error in the code, that has been fixed in the solution posted above; and you can simplify this even further with DeMorgan, if you want to.
The syntax of an OR operator requires a boolean expression on its left and another boolean expression on its right. There's no factoring out any common expression or part thereof.if (input.equalsIgnoreCase("N") || "NO") return; if (input.equalsIgnoreCase("N") || input.equalsIgnoreCase("NO") ) return;
First offint x = console.readDouble(); if (x != null) y = y + x; double x = console.readDouble(); y = y + x;
readDouble
returns a
floating point number so the receiving variable should be able to hold the
fractional part. Then, a number cannot be compared with null
because their types are different: primitive vs. reference type.
Finally,
to fix the code you have two options: either drop the if
statement (which is what we did above) or turn the code around by using
try
and catch
instead (as
explained in chapter 2), to specify what needs to be done if the user does
not enter a number at all, and just presses Return
(which presumably the original code was trying to do too).
The original code was missing a pair of braces. Without them the sequence of decisions will never reach a situation where thelanguage = "English"; if (country.equals("USA")) if (state.equals("PR")) language = "Spanish"; else if (country.equals("China")) language = "Chinese"; language = "English"; if (country.equals("USA")) { if (state.equals("PR")) language = "Spanish"; } else if (country.equals("China")) language = "Chinese";
country
variable will be checked
for being "China"
as the else
statement is actually attached
to the second if (the one that checks if state is "PR"
) which is reached when
the String
variable by the name of country
is
"USA"
already).
A syntactical construct that is made up of constants, variables, method calls, and operators combining them:
(a.length() >= 6)
An expression whose type (or final value) is boolean
(and we have already
given an example of that above).
A syntactical unit in a program. In Java a statement is either a simple statement, a compound statement, or a block.
x = x + 1;
Simple statements are atomic (more or less).
System.out.println("Atoms are complicated.");
Compound statements contain (are composed of) simple statements but not the other way around. Compound statements can contain other compound statements as well.
if (x != 0) x = 0;
Compound statement that contains one or more statements inside it (simple or compound) and groups them together with the help of curly braces.
Advanced topic 6.1 (on page 230, in chapter 6, next chapter) contains extremely important information about blocks. Meanwhile we have seen blocks being used here in{ x = 10; x += 1; x += 1; }
if
statements to avoid the dangling else
problem.
if/else /else
statement and
nested if statements. Give an example for each.
The first is a particular case of the second. The particular aspect of the first one is its linear structure: the structure is in fact identical to the one that theswitch
statement has, except theswitch
is not nearly as powerful. (Why?)As for examples, see pages 195-198 for details.
if/else /else
statement where the order
of the tests does not matter. Give an example where the order of the tests matter.
The problem asks for one and the same structure so in our examples the two structures are identical. But if we move the conditions (and their corresponding alternatives, of course) around (for example by first checking for anif (score >= 96 ) grade = "A+"; if (score >= 96) grade = "A+"; else if (score >= 90 && score < 96) else if (score >= 90) grade = "A" ; grade = "A" ; else if (score >= 88 && score < 90) else if (score >= 88) grade = "A-"; grade = "A-"; else grade = "B" ; else grade = "B" ;
A-
) then the first of the two examples will
still produce the right result, whereas the second one will produce only A-
's
and B
's. The difference between the two implementations, of course, is that in the first one the conditions are distinct, disjoint, non-overlapping, whereas in the second one they're not.
The question is, of course, why -- because the actual answers can be easily checked with the help of a computer:"Tom" , "Dick" "Tom" , "Tomato" "church" , "Churchill" "car manufacturer", "carburetor" "Harry" , "hairy" "C++" , "Car" "Tom" , "Tom" "Car" , "Carl" "car" , "bar"
For the why of it check pp. 191-192 in the book.frilled.cs.indiana.edu%cat Check.java public class Check { public static void main(String[] args) { System.out.println( "Tom vs. Dick " + "Tom".compareTo("Dick")); System.out.println( "Tom vs. Tomato " + "Tom".compareTo("Tomato")); System.out.println( "church vs. Churchill " + "church".compareTo("Churchill")); System.out.println( "\"car manufacturer\" vs. carburetor " + "car manufacturer".compareTo("carburetor")); System.out.println( "Harry vs. hairy " + "Harry".compareTo("hairy")); System.out.println( "C++ vs. Car " + "C++".compareTo("Car")); System.out.println( "Tom vs. Tom " + "Tom".compareTo("Tom")); System.out.println( "Car vs. Carl " + "Car".compareTo("Carl")); System.out.println( "car vs. bar " + "car".compareTo("bar")); } } frilled.cs.indiana.edu%javac Check.java frilled.cs.indiana.edu%java Check Tom vs. Dick 16 Tom vs. Tomato -3 church vs. Churchill 32 "car manufacturer" vs. carburetor -66 Harry vs. hairy -32 C++ vs. Car -54 Tom vs. Tom 0 Car vs. Carl -1 car vs. bar 1 frilled.cs.indiana.edu%
p
, q
,
and r
.
p |
q |
r |
(p && q) || !r |
!(p && (q || !r)) |
---|---|---|---|---|
false | false | false | true | true |
false | false | true | false | true |
false | true | false | true | true |
false | true | true | false | true |
true | false | false | true | false |
true | false | true | false | true |
true | true | false | true | false |
true | true | true | true | false |
How do we check if we are right or wrong? We ask the computer:
frilled.cs.indiana.edu%cat Boole.java public class Boole { public static void main(String[] args) { boolean p, q, r; p = false; q = false; r = false; System.out.println( ((p && q) || !r) + " " + (!(p && (q || !r))) ); p = false; q = false; r = true; System.out.println( ((p && q) || !r) + " " + (!(p && (q || !r))) ); p = false; q = true; r = false; System.out.println( ((p && q) || !r) + " " + (!(p && (q || !r))) ); p = false; q = true; r = true; System.out.println( ((p && q) || !r) + " " + (!(p && (q || !r))) ); p = true; q = false; r = false; System.out.println( ((p && q) || !r) + " " + (!(p && (q || !r))) ); p = true; q = false; r = true; System.out.println( ((p && q) || !r) + " " + (!(p && (q || !r))) ); p = true; q = true; r = false; System.out.println( ((p && q) || !r) + " " + (!(p && (q || !r))) ); p = true; q = true; r = true; System.out.println( ((p && q) || !r) + " " + (!(p && (q || !r))) ); } } frilled.cs.indiana.edu%javac Boole.java frilled.cs.indiana.edu%java Boole true true false true true true false true true false false true true false true false frilled.cs.indiana.edu%
A && B
is the same as B && A
for any Boolean
conditions A
and B
?
For all practical purposes in this class: yes, but check at the bottom of page 208 for "lazy evaluation". We will revisit this question later, in chapter 7.
ands = 0; if (x > 0) s++; if (y > 0) s++;
The first of the two contains three statements one after another. The second one only two. For x > 0 and y > 0 the first code sets s to 2, while the second one to 1, incrementing only once. Draw the diagrams to see the effect of thes = 0; if (x > 0) s++; else if (y > 0) s++;
else
alternative.
!(x > 0 && y > 0) x <= 0 || y <= 0
!(x != 0 || y != 0) x == 0 && y == 0
!(country.equals("USA") && !state.equals("HI") && !state.equals("AK")) !country.equals("USA") || state.equals("HI") || state.equals("AK")
!(x % 4 != 0 || !(x % 100 == 0 && x % 400 == 0)) x % 4 == 0 && (x % 100 == 0 && x % 400 == 0) This can be further simplified tox % 400 == 0
-else
problem, using the following statement. A student with a GPA of at least 1.5, but less
than 2, is on probation. With less than 1.5, the student is failing.
Without the curly braces theif (gpa > 1.5) { if (gpa < 2) System.out.println("Probation."); } else System.out.println("Failing.");
else
would migrate (change position).
==
operator and the
equals
method when comparing strings.
The first operator checks if the two String
s are
stored in the same place (which means that they are in fact one and the same object). The other
one checks to see if they would look the same if printed (case sensitive). You should always use
the second one over the first.
Also see sections 5.2.3 and 5.2.4 in the book.
andr == s
where bothr.equals(s)
r
and s
are of type Rectangle
.
The first operator checks if the two Rectangle
s are
stored in the same place (which means that they are one and the same object). The other one checks
to see if you knew you drew more than one if you were to draw them (if one equals
the other they'd be drawn on top of each other and as such you wouldn't be able to tell two have
been drawn instead of one).
Also see sections 5.2.3 and 5.2.4 in the book.
r
is null
?
What happens when this code runs?
If the variable does not get initialized before the test we would get an error message at compile time. Otherwise it depends how theRectangle r; ... if (r.equals(null)) r = new Rectangle(5, 10, 20, 30);
equals
method is implemented in class Rectangle
and you would find that here. (If the variable
r
points to a real Rectangle
the result can only be false
).
To check if r
is null
or not use the ==
operator.
Write Java code to test whether two objects of type
Line2D.Double
represent the same line when displayed
on the graphics screen. Do not use a.equals(b)
.
Hint: IfLine2D.Double a; Line2D.Double b; if (a.getP1().equals(b.getP1()) && a.getP2().equals(b.getP2()) || a.getP1().equals(b.getP2()) && a.getP2().equals(b.getP1()) || ) g2.drawString("They look the same!", x, y);
p
and q
are
points, then Line2D.Double(p, q)
and
Line2D.Double(q, p)
look the same.
Check the API for accessors used in the condition above (which is implementing the hint).
n
equals
10 and whether a floating-point number x
equals 10.
Inevitable lack of precision, with floating-point numbers.
For an integer n
this would be a good test:
For a floating-point numbern == 10
x
this would be a good test:
Also see section 5.2.2 in the book and the following (next) exercise in this quiz.Math.abs(x - 10) <= 1E-14 * Math.max(Math.abs(x), Math.abs(y))
x
and y
such that Math.abs(x - y)
is larger than 1000, but x
and
y
are still identical except for a roundoff error. For example
1E18
vs.
(1E18 + 1001)
To see how this could happen consider the following:
frilled.cs.indiana.edu%cat Test.java class Test{ public static void main(String[] args) { double x = 10.0; // original value double y = Math.sqrt(x); // compute square root double z = y * y; // recover the original number (hopefully) System.out.println("x = " + x + " y = " + y + " z = " + z); // so z and x are "the same" now -- hopefully we agree on that double result = (x - z); // but result is > 0 (though small enough) // so yes, x and z are one and the same (really) System.out.println(x + " - " + z + " = " + result); // so x and z are equal (approximately) x = x * 1E18; z = z * 1E18; // they're still equal, aren't they - multiplied by the same number System.out.println(x + " is a roundoff error of\n" + z); System.out.println("Their difference: " + (x - z)); // so look at their difference now, equal as x and z are // difference is now 2,048 but absolute value means nothing // it's the ratio of this error to the magnitude of the two // numbers that really counts 2,048/1e18 is still 1e-14... } } frilled.cs.indiana.edu%javac Test.java frilled.cs.indiana.edu%java Test x = 10.0 y = 3.1622776601683795 z = 10.000000000000002 10.0 - 10.000000000000002 = -1.7763568394002505E-15 1.0E19 is a roundoff error of 1.0000000000000002E19 Their difference: -2048.0 frilled.cs.indiana.edu%
Consider the following test to see whether a point falls inside a rectangle.
Rewrite this code to eliminate the explicitPoint2D.Double p = ... boolean xInside = false; if (x1 <= p.getX() && p.getX() <= x2) xInside = true; boolean yInside = false; if (y1 <= p.getY() && p.getY() <= y2) yInside = true; if (xInside && yInside) g2.drawString("p is inside the rectangle.", x1, y1);
true
and false
values,
by setting xInside
and yInside
to the values of Boolean expressions.
We mentioned in class thatPoint2D.Double p = ... boolean xInside = (x1 <= p.getX() && p.getX() <= x2); boolean yInside = (y1 <= p.getY() && p.getY() <= y2); if (xInside && yInside) g2.drawString("p is inside the rectangle.", x1, y1);
is equivalent toboolean a; if (<condition>) a = true; else a = false;
always. So we can often simplify, as needed.boolean a = <condition>;