Second Summer 2002


Iffy Practice Problems: This is textbook chapter 5. Warmups. The Solutions.
Questions:

  1. Find the errors in the following if statements.

    After each statement we list the correct version annotated in blue.

    if quarters > 0 then System.out.println(quarters + "quarters"); 
    
    if (quarters > 0) then System.out.println(quarters + "quarters");
    Condition must be enclosed in parens, and there is no then keyword in Java.


    if (1 + x > Math.pow(x, Math.sqrt(2)) y = y + x;
    
    if (1 + x > Math.pow(x, Math.sqrt(2))) y = y + x;
    Condition must be enclosed in parens, and one parenthesis was missing.


    if (x = 1) y++; else if (x = 2) y = y + 2; 
    
    if (x == 1) y++; else if (x == 2) y = y + 2; 
    We should always remember to use == to test for equality as = is used exclusively for assignment.


    if (x && y == 0) p = new Point2D.Double(x, y);
    
    if (x == 0 && y == 0) p = new Point2D.Double(x, y);
    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 (1 <= x <= 10)
    { System.out.println("Enter y:");
      y = console.readDouble();
    } 
    
    if (1 <= x && x <= 10)
    { System.out.println("Enter y:");
      y = console.readDouble();
    } 
    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 (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!");  
    Remember to use equals when comparing Strings. (!= 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.


    if (input.equalsIgnoreCase("N") || "NO") 
      return;  
    
    if (input.equalsIgnoreCase("N") || 
        input.equalsIgnoreCase("NO")  )
      return;
    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.


    int x = console.readDouble();
    if (x != null) y = y + x; 
    
    double x = console.readDouble();
    y = y + x;
    First off 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).


    language = "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"; 
    The original code was missing a pair of braces. Without them the sequence of decisions will never reach a situation where the 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).


  2. Explain the following terms and give an example for each construct:

  3. Explain the difference between an 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 the switch statement has, except the switch is not nearly as powerful. (Why?)

    As for examples, see pages 195-198 for details.

  4. Give an example for an if/else /else statement where the order of the tests does not matter. Give an example where the order of the tests matter.
    if (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" ;             
    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 an 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.

  5. Of the following pairs of strings, which comes first in lexicographic order?
    "Tom"             , "Dick"
    "Tom"             , "Tomato"
    "church"          , "Churchill"
    "car manufacturer", "carburetor"
    "Harry"           , "hairy"
    "C++"             , "Car"
    "Tom"             , "Tom"
    "Car"             , "Carl"
    "car"             , "bar"
    The question is, of course, why -- because the actual answers can be easily checked with the help of a computer:
    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%
    For the why of it check pp. 191-192 in the book.

  6. Complete the following truth table by finding the truth values of the Boolean expressions for all combinations of the Boolean inputs 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%

  7. True or false: 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.

  8. Explain the difference between
    s = 0;
    if (x > 0) s++;
    if (y > 0) s++;
    and
    s = 0;
    if (x > 0) s++;
    else 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 the else alternative.

  9. Use De Morgan's law to simplify the following Boolean expressions.
    !(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 to

    x % 400 == 0

  10. Make up another Java code example that shows the dangling-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.
    if (gpa > 1.5)  {
      if (gpa < 2) 
        System.out.println("Probation."); 
    } else System.out.println("Failing.");
    Without the curly braces the else would migrate (change position).

  11. Explain the difference between the == operator and the equals method when comparing strings.

    The first operator checks if the two Strings 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.

  12. Explain the difference between the tests
    r == s
    and
    r.equals(s)
    where both r and s are of type Rectangle.

    The first operator checks if the two Rectangles 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.

  13. What is wrong with this test to see whether r is null? What happens when this code runs?
    Rectangle r;
    ...
    if (r.equals(null))
      r = new Rectangle(5, 10, 20, 30);
    If the variable does not get initialized before the test we would get an error message at compile time. Otherwise it depends how the 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.

  14. Note: For this exercise some facts from Chapter 4 are needed.

    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).

    Line2D.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);
    Hint: If 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).

  15. Explain why it is more difficult to compare floating-point numbers than integers. Write Java code to test whether an integer 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:

    n == 10
    For a floating-point number x this would be a good test:
    Math.abs(x - 10) <= 1E-14 * Math.max(Math.abs(x), Math.abs(y))
    Also see section 5.2.2 in the book and the following (next) exercise in this quiz.

  16. Give an example for two floating-point numbers 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%

  17. Note: For this exercise some facts from Chapter 4 are needed.

    Consider the following test to see whether a point falls inside a rectangle.

    Point2D.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);
    Rewrite this code to eliminate the explicit true and false values, by setting xInside and yInside to the values of Boolean expressions.
    Point2D.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);
    We mentioned in class that
    boolean a;
    if (<condition>) 
      a = true;
    else 
      a = false; 
    is equivalent to
    boolean a = <condition>;
    always. So we can often simplify, as needed.


Last updated: Jun 16, 2002 by Adrian German for A201