Homework 9: Immutable Objects


  • Perform arithmetic using arrays and BigInteger.
  • Write JUnit tests that pass with 100% coverage.

Note: JUnit is a simple framework to write repeatable tests, and JaCoCo is a code coverage analysis tool for Java. Some of these exercises assume you already know how to use JUnit and JaCoCo in your development environment.

Exercise 9.1   CodingBat Array-1

You should work on 9.2 before 9.1 since it is creating tests for 9.1.  As a review of Homework 7, this exercise will have you solve a few more CodingBat problems from the Array-1 category. But there's a catch: you must validate the parameters before using them. That way, your program won't crash if given invalid arguments.

Download the BatArray1.java source file and read the Javadoc comments first. Implement these methods offline, and then test your code using the links below. Once you have it passing 100% on CodingBat, submit your code to Autolab, which will run additional tests with invalid inputs.

  • commonEnd
    CodingBat says, "Both arrays will be length 1 or more." But Autolab will try sending you empty arrays and null.

  • midThree
    CodingBat says, "The array length will be [odd and] at least 3." But don't assume that will be the case on Autolab.

  • maxTriple
    CodingBat says, "The array length will be [odd and] at least 1." Again, don't assume that will be the case in general.

Your solution must NOT use loops, and it must NOT use any library classes. Autolab will automatically reject submissions containing words like for, while, Arrays, and Math.

Exercise 9.2   Testing Array-1

Implement a test class named BatArray1Test that tests all the functionality of Exercise 9.1, including the invalid arguments. When you submit your code to Autolab, it will run against the instructor's solution for BatArray1. Note that you will need to test each method multiple times in order to get 100% coverage. Write a variety of assertions for both valid and invalid arguments.

Be sure to use the correct type of assertion for each problem. For commonEnd, which returns a boolean, use assertTrue and assertFalse. For midThree, which returns an array, use assertArrayEquals and assertNull. For maxTriple, which returns an integer, simply use assertEquals.

Hint: You might want to work on this exercise before attempting Exercise 9.1 above. That way, you'll be able to test your BatArray1 code offline before submitting it to Autolab.

Exercise 9.3   Big Fractions

You should work on 9.4 before 9.3 since it creates tests for 9.3.  It's amazing what you can do with the BigInteger class. Not only does it support "arbitrary-precision" arithmetic (i.e., min/max values are limited only by the amount of memory available), it also has many useful methods. According to the documentation:

BigInteger provides analogues to all of Java's primitive integer operators, and all relevant methods from java.lang.Math. Additionally, BigInteger provides operations for modular arithmetic, GCD calculation, primality testing, prime generation, bit manipulation, and a few other miscellaneous operations.

Imagine you were given a "big fraction" as part of an elementary school math assignment:

4,000,000,000,000,000,000,000,000 (i.e., 4 septillion)
8,000,000,000,000,000,000,000,000 (i.e., 8 septillion)

At some point in life, you learned how to reduce fractions like this one. Back then, the numerator and denominator probably didn't have 25 digits. Most calculators can't handle numbers like that, and they're a pain to deal with by hand. Fortunately we have BigInteger, and reducing fractions is fairly easy: just divide the numerator and denominator by their greatest common divisor. (Did you notice there's a BigInteger method for that?)

Create a new class named BigFractions that contains the method: public static String reduce(BigInteger numer, BigInteger denom). The method returns a string, because you need to format your answer using mixed fractions. Here are some example arguments and return values:

  • reduce(14, 4) → "3 and 1/2"
  • reduce(10, 12) → "5/6"
  • reduce(12, 3) → "4"
  • reduce(1, 0) → "ERROR"

Notice that the whole number and fractional parts are omitted when they are zero (i.e., it doesn't return "0 and 5/6" or "4 and 0/3"). It also avoids dividing by zero and returns the string "ERROR" in that case.

Your solution must NOT use loops. Autolab will automatically reject submissions containing words like for and while.

Exercise 9.4   Testing Fractions

Implement a test class named BigFractionsTest that tests all the functionality of Exercise 9.3, including special cases. When you submit your code to Autolab, it will run against the instructor's solution for BigFractions.

To help you get 100% coverage, we recommend you implement the following test methods:

  • testImproperFrac() → tests improper fractions (i.e., numer > denom)
  • testProperFrac() → tests proper fractions (i.e., numer < denom)
  • testWholeNumber() → tests whole numbers
  • testDivByZero() → tests the ERROR case

Hint: You might want to work on this exercise before attempting Exercise 9.3 above. That way, you'll be able to test your BigFractions code offline before submitting it to Autolab.

Exercise 9.5   Command-Line Calc

Good news! After so many weeks of seeing public static void main(String[] args), we're finally going to use the variable args. Create a program named CmdLineCalc.java that works like a simple calculator. You'll run this program from the command line:

$ java CmdLineCalc 1 + 2

$ java CmdLineCalc 1 - 2.5

$ java CmdLineCalc 3 + 4 - 5

$ java CmdLineCalc 6.5 - 7 + 8

To keep it simple, your program only needs to support addition (+) and subtraction (-). You may assume that, starting with the first argument, every other argument will be a number. The arguments at odd indexes in the array will be operators. There is no limit to the number of arguments, that is, until the computer runs out of memory. The program should display the answer rounded to one decimal place.

There are three types of errors you need to handle: 1) the user might forget to give you command-line arguments, 2) the expression itself might be incomplete, and 3) the user might use operators you don't support. Here is what you should output in those cases:

$ java CmdLineCalc
Missing expression

$ java CmdLineCalc 1 +
Invalid expression

$ java CmdLineCalc 2 % 3
Invalid operator: %

When an error occurs, display the appropriate message and call System.exit() to terminate the program. Use a status of 1 to indicate that an error occurred. (By default, programs exit with a status of 0, meaning success.)

You should test this exercise directly from the command line, rather than use JUnit. Writing JUnit tests that automatically capture System.out and deal with System.exit requires advanced techniques beyond the scope of this chapter.

Submissions for all problems for HW9 should be made to https://autolab.cs.jmu.edu 


Back to Top