RU beehive logo ITEC dept promo banner
ITEC 120
2008spring
ibarland,
jdymacek

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs

lab05b
comparing doubles
witnessing bad arithmetic

We start by trying some expressions from lecture, to confirm that Java doesn't always give correct arithmetic answers. Predict the result of each expression to your partner, then try them out:

Challenge: For each of above, classify the error as

  1. round-off error (can only happen with floating-point arithmetic, not ints)
  2. overflow: a number so big it can't be represented (can happen with integer or floating-point arithmetic)
  3. underflow: a number so small it's considered zero (can only happen with floating-point arithmetic) (we didn't talk about this in lecture)

Order of operations

Practicing with quotient, remainder

Remember that /, if given two integers, returns the quotient. The remainder can be obtained by % (pronounced “mod” or “modulo” in addition to “remainder”). Predict the result of each expression to your partner, then try them out:

Comparing doubles

Edict of Programming: Do not use == with doubles.
After all, what is the value of this expression?
(2.0 - 1.1) == 0.9
So how do we see if two doubles are practically-equal? One immediate imponderable is “how close is close enough to be considered practically equal”? Well, for the moment let's say being within 0.001 is close enough: (y-0.001) < x < (y+0.001) is a start. (How do we write this math expression in Java? We'll need to use &&!) The amount “0.001” is called the “tolerance” of the comparison.

Task A (Practice with booleans): Write a function nearlyEqual which takes in two doubles, and returns whether or not they are within 0.001 of each other. (Use a named-constant for the tolerance.)

Task B Write nearlyEqual_v2 which is like the previous version, but the tolerance is one of the inputs to the method. (This is nice because it lets the person calling your function decide for themselves, what constitutes “close enough” for their specific purpose.)

Task C, optional (Practice with number-sense): Actually, we should look at an relative difference between two terms, rather than an absolute difference. After all, 1.0 and 2.0 are quite different (difference of 1.0), but a trillion dollars and a trillion-and-one dollars are practically the same (difference of 1.0)

Modify your program so that it returns true if the ratio of the two numbers is close to 1: that is, if (1-0.0001) < x/y < (1+0.0001). What is a test case for which this formula doesn't make work? Can you fix your code to handle that test case?1

Counting with mod

When counting musical beats, one repeats counting every measure: “1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1…”. Computer scientists count music similarly, but they count from 0 to 3: “0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0…”. (Computer scientists are only familiar with music in 4/4. 3 or 6 (or 5) beats per measure isn't a power of two, and isn't music worth counting out. And for music in 2/4, true computer scientists use booleans :-)

Task D

class ModMaster {

  /** Count out beats in 4/4, computer-science style (0-3).
   * @param currentBeat The current count, a number in {0,1,2,3}.
   * @return The next beat to be counted out.
   *  Test cases (presuming `mm` is an instance of ModMaster):
   *    mm.nextBeatIn4( 0 ) = 1
   *    mm.nextBeatIn4( 1 ) = 2
   *    mm.nextBeatIn4( 2 ) = 3
   *    mm.nextBeatIn4( 3 ) = 0
   */
  int nextBeatIn4( int currentBeat ) {
    return 17;
    // Can you write an implementation which
    // doesn't use `if`?  Hint: use `%`.
    }
 


  /** Return the length of a movie in "h:mm" format.
   * @param minutes The length of the movie, in minutes.
   * @return the length of a movie in "h:mm" format.
   *  Test cases (presuming `mm` is an instance of ModMaster):
   *    mm.movieTimeHM(  0) = "0:00"
   *    mm.movieTimeHM(120) = "2:00"
   *    mm.movieTimeHM(130) = "2:10"
   *    mm.movieTimeHM( 59) = "0:59"
   *    mm.movieTimeHM( 60) = "1:00"
   *    mm.movieTimeHM( 61) = "1:01"
   */
  String movieTimeHM( int minutes ) {
    return "stub function...";
    }
 
  /** Return the length of a movie in hours and minutes,
   *  using indicated separator and suffix:
   * @param minutes The length of the movie, in minutes.
   * @param separator A string to insert between the hours and the minutes.
   * @param suffix A string to add after the minutes.
   * @return the length of a movie in hours and minutes,
   *  using indicated separator and suffix:
   * @see movieTimeHM
   *
   *  Test cases (presuming `mm` is an instance of ModMaster):
   *    mm.movieTimeHMCustom(130, "h", "m") = "2h10m"
   *    mm.movieTimeHMCustom(130, " hours, ", " min") = "2 hours, 10 min"
   *    mm.movieTimeHMCustom(130, ":", "") = "2:10"
   */
  String movieTimeHMCustom( int minutes, String separator, String suffix ) {
    return "stub function...";
    }


  // After completing movieTimeHMCustom,
  // re-write movieTimeHM to avoid repeated code.
  }

We won't check off these functions in lab, but they are worth completing as quiz1-study-material.


1 A more subtle wrinkle: is your function symmetric — that is, if your program says that a is nearly equal to b, does that mean it will always say that b is nearly equal to a? If not, is this easy to fix? Is is important to fix it?      

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs


©2008, Ian Barland, Radford University
Last modified 2008.Feb.14 (Thu)
Please mail any suggestions
(incl. typos, broken links)
to iba�rlandrad�ford.edu
Powered by PLT Scheme