CS210

Project 1

Bob Wilson

 

Writing a Java Class to Satisfy a Provided API and JUnit TestCase

 

Some applications involve polynomials which can be modeled as “objects” in an Object-Oriented Programming program.  Hence, we need a class named Polynomial that can be used to create and operate on polynomials.  In this project, you will write a class that implements polynomials and polynomial arithmetic. 

 

I have provided a Project1.zip with a JUnit TestCase class that you can use to test your Polynomial class.  Unzip the directory and setup a Dr Java project.  In your Dr Java project, create/save a new source file named Polynomial.java and write your code in it, compile it, and test it.  Keep testing it until the code for your Polynomial class passes all the test cases in TestPolynomial (shows all green).

 

The UML class diagram describing the API for the Polynomial class is provided here.

 

Polynomial implements Comparable<Polynomial>

- coefficients : ArrayList<Integer> // polynomial coefficients

 

+ Polynomial(int... coefficients) // constructor with variable length coefficients

+ toString( ) : String            // return a String representing the polynomial

+ compareTo(that : Polynomial) : int          // returns -, 0, +

+ equals(that : Polynomial) : boolean         // returns true or false

                                  // Polynomial arithmetic methods:

+ plus(that : Polynomial) : Polynomial        // add

+ minus(that : Polynomial) : Polynomial       // subtract

+ multiply(that : Polynomial) : Polynomial

+ divide(divisor : Polynomial) : Polynomial [] {[0] = quotient, [1] = remainder}

+ evaluate(x : double) : double   // return the value of polynomial evaluated for x

+ derivative() : Polynomial       // return the derivative of the Polynomial

+ root(guess : double, TOLERANCE : double, iterations : int) : double  // get root

 

The Polynomial class encapsulates one private ArrayList<Integer> of coefficients.  The value for each array element is the coefficient of that exponent in the polynomial.  For example:  An array with coefficients[0] = 1, coefficients [1] = -2, and coefficients[2] = 2 represents the polynomial  2*x2 - 2*x1 + 1*x0 (or more compactly 2x2 - 2x + 1). 

 

The polynomial class implements the interface Comparable<Polynomial>.  An object of your Polynomial class can be compared to other Polynomial class objects so we will write the code in the class header as implements Comparable<Polynomial>. 

 

Code outside of your Polynomial class can do the following:

 

1. Create a Polynomial object by calling the Polynomial constructor with a list of int variables for the coefficients starting with the coefficient of x0 and ending with the coefficient for the largest power of x present.  Here is an example:

 

     // create a polynomial corresponding to above example

     Polynomial p = new Polynomial(1, -2, 2);  // representing 2*x2 - 2*x1 + 1*x0

 

Notice that after code outside of the Polynomial class creates a Polynomial object with terms for all exponents, it does not ever need to access the coefficients again.  Hence, there are no mutator (“setter”) or accessor (“getter”) methods.  All operations on the coefficients of Polynomial objects are done in the code of the Polynomial class itself, for example:

 

2. Display Polynomial objects using the toString method, for example:

 

            // print a polynomial

     System.out.println(p.toString());

 

The String representing a polynomial is a concatenation of the coefficients in the array and their corresponding powers of x.  See the provided TestPolynomial class to understand the exact format your code needs to produce.  Although the ^ symbol is not used as an exponentiation operator in Java, we use it to indicate superscripting in the string representation of our polynomials.

 

3. Compare two polynomials via the compareTo method.  This is the method required to implement the interface Comparable.  Look up the interface Comparable on the Sun web site and study the meaning of implementing this interface.  You should also include an equals method for comparisons.

 

            // compare two polynomials p and q

     int n = p.compareTo(q);       // n = -, 0, or + value based on comparision

     boolean b = p.equals(q);      // b = true or false based on comparison

 

The compareTo method implements the “natural ordering” of polynomials as follows:

 

                        A polynomial is lower than a polynomial with a non zero coefficient of a higher power.

                        If the number of coefficients is the same, a polynomial is lower based on the lower of the largest coefficient that is different.

                        If the number of coefficients and all the coefficients of each power are the same, the polynomials are equal.

           

Once you have written a compareTo method, you can use it to write a simple equals method.  Return true or false based on the return value from a call to the compareTo method being equal to 0 or not.

 

4. Do arithmetic on Polynomials using the arithmetic methods of the Polynomial class, for example:

 

     Polynomial sum = p.plus(q);       // return sum of p + q

     Polynomial diff = p.minus(q);     // return result of p - q

     Polynomial product = p.multiply(q);     // return product of p * q

     Polynomial [] qr = p.divide(q);         // return quotient and remainder of p / q

 

Note that these methods are normal methods and are called the same way as normal methods.  They are not “magic methods” like in Python and do not overload the operators: +, -, *, and /.  Operator overloading is not supported in Java.

 

5. Evaluate the polynomial at a specific value of x

 

     // evaluate polynomial with x = 3 and print the value

     System.out.println(p.evaluate(3));

 

6. Obtain a Polynomial that represents the derivative (slope function) of the existing Polynomial

 

     // obtain the derivative and print the function

     System.out.println(p.derivative());

 

8. Obtain an estimate of a root of the Polynomial using Newton’s method - providing an initial guess, a required tolerance, and a maximum number of iterations to use.  

 

     // obtain a root of the Polynomial using Newton’s method

     System.out.println(p.root(1.5, 0.0001, 10));   // guess, tolerance, iterations

 

Notes on the implementation:

 

The Constructor

For the constructor, we are using the variable length argument list capability of the Java language.  We declare the method header for the overloaded constructor as follows:

 

public Polynomial(int... coefficients);   // a list of ints will be placed in an array.

 

Our code can call this constructor either of two ways:  with an arbitrarily long list of int variables or one variable of type int [ ].

 

Normally, we would think that the highest power of x in the polynomial would be the length of the array minus one.  However, the user may provide a list of variables with zero values for the larger indexed coefficients in the array.  Hence the length of the array does not directly indicate the degree of the polynomial.  After copying the coefficients array into the ArrayList attribute, loop through the ArrayList and remove any high order zero coefficients.  Now the ArrayList size() method indicates the order of the polynomial.

 

Arithmetic Methods

 

The methods implementing the polynomial arithmetic should operate on the coefficients of “this” polynomial with the coefficients of “that” polynomial.  The word “that” is not a Java reserved word.  We can use it for a variable name in the parameter list.   For example, use as the method header for plus:

 

            public Polynomial plus(Polynomial that)

 

Calculate the new coefficients for the result of each arithmetic method and return them in a new Polynomial object, as follows:

 

Allocate a result array large enough to hold the coefficients of the sum/difference (larger of the two ArrayList sizes).

Execute the required steps to perform the arithmetic.

Calculate new coefficients and store them in the array.

Construct and return a new polynomial using the array of coefficients that you calculated above.

 

Derivative method

 

In calculus, the derivative of a term in a polynomial can be calculated easily.  The derivative of the term Cnxn is n*Cnx(n – 1).  The derivative of the entire polynomial is the sum of the derivatives of every term.  Use the Polynomial arithmetic methods as needed.

 

Root Method

 

The root method needs to implement a loop refining the initial guess at each iteration i using Newton’s method and the Polynomial arithmetic, derivative, and evaluate methods.

 

            guess(i + 1) = guess(i) – polynomial value at guess(i) / derivative value at guess(i)

 

The loop should terminate when the value of the polynomial at guess(i) is within the TOLERANCE of zero, the derivative at guess(i) is zero (failure of Newton’s method), or the number of iterations is exceeded (to prevent infinite loops).

 

General Guidelines

 

Include Javadoc comments in your Polynomial class code with @author and @version for the class and with @param and @return for each method.  In the Javadoc comments for each method, include a brief description of the calculation that your code performs.  Run javadoc on your Polynomial class file to create a webpage describing the API to your Polynomial class.  Keep improving the Javadoc comments in your code until it produces a readable and useful webpage.  Include a copy of this javadoc generated webpage in your project folder.

 

Now, write an application class with a name of your own choosing and a main method.   Use your javadoc webpage and the Sun webpage for the java.util.Arrays class as guidance while you are writing the code for this class.  You should find it easy to create and do operations on polynomials without knowing much about the mathematics of them.  In the Arrays class webpage, locate the sort(Object [] a) method described there.  Note that it requires an array of Objects that have a natural ordering based on the Comparable compareTo method. 

 

The main method should instantiate an array of at least 5 Polynomial objects and instantiate a different Polynomial object in each element of the array.  Be sure that you put them in the array out of their natural ordering so that you can see the results of sorting the array.  Have your code print out the Polynomial objects in your array before sorting them, call Arrays.sort to sort the array of Polynomials, and print out the contents of the array again to show that they are now sorted in their natural order based on the rules given above for the Polynomial class compareTo method. 

 

Using the Dr Java Debugger

 

Many students start out testing their programs by putting a lot of System.out.println statements (“debug write statements”) in their code to see its progress during execution.  However, given the debugging capabilities of modern software development tools, this is a poor practice. We don’t want you to submit your code for grading with any debug write statements in it.  However, it will be more difficult than you expect to remove all of those “debug write” statements from your code before submitting your code because it is easy to delete some needed lines of code along with the debug write statements.  (The editor is the most dangerous software development tool!)  In effect, you need to retest your code against all test cases after removing the debug write statements.  In a more substantial project, this may be a waste of time and effort.

 

DrJava has a built-in debugger.  You will benefit from learning to use this capability during this project and during subsequent labs and projects.  The DrJava debugger gives you the ability to set a “breakpoint” at one or more specific lines in your code.  When you run your program in “debug” mode, DrJava will stop the execution of your program at the first breakpoint that it encounters.  You usually set breakpoints at lines of code based on one of two criteria: 

1) You want to know if the execution of your code gets to that point in your program or not, i.e. that the flow of control reaches that line of code when you expect or that it does not reach that line of code when you do not expect it to get there.

AND/OR

2) You want to look at the values of local variables at that point in the execution of your program to check the correctness of computations done up to that point.

 

To use the Dr Java debugger, you use the “Debugger” menu.  Here are some basic instructions for using it.  Use the DrJava Help feature to learn more about using the debugger.

 

Setting/Resetting a breakpoint:

In the edit window, set your cursor to a line of code where you want to set a breakpoint.  In the Debugger menu, select “Toggle Breakpoint on Current Line”.  When the breakpoint is set, DrJava will show that line of code highlighted in red.  To reset a breakpoint, set your cursor on a line of code where a breakpoint has been previously set and select “Toggle Breakpoint on Current Line” again or select “Reset all Breakpoints”.

 

Running in Debug Mode:

Go to the “debugger” menu and check the box “Debug Mode” prior to running your program.  DrJava will display a debug panel between your edit window and Interactions panel. The debug panel has three sections: The Watches section on the left where you can enter the names of variables whose current values you want to see.  The Stack/Threads section where the Stack tab shows you the sequence of method calls into the line of code at the breakpoint. (Don’t bother looking at the Threads tab as you will probably not understand that information this early in your programming education.)  At the right, there is a section containing buttons that allow you to resume execution of your program or to single step through your program starting from that breakpoint.

 

Run your program as normal. Interact with your program normally until DrJava indicates that you have hit a breakpoint and shows the currently executing line of code in blue.  While DrJava has your program “suspended” at this breakpoint, it will allow you to look at individual variable values in the watches section of the debug panel.  Note that the variables must be “in scope” at that line of code, i.e. that they are accessible to code at point in your program.

 

You will need to experiment with the debugger to learn how to use it effectively and efficiently.  Here is a simple example for trying the debugger for the first time:  Follow the instructions above to set a breakpoint on the “return result;” line of code in the QuadraticSolver getSolution method, set debug mode, and run the program.  Enter a, b, and c values in response to the QuadraticCLI prompts.  DrJava should eventually indicate that you have reached the breakpoint.  Enter the name of the variable in the first line of the Watch section and you should see the value at that point of execution.

 

Report (memo.txt)

 

For this project and all projects in this course, the memo.txt file that you upload to the turn-in system MUST BE A PLAIN TEXT FILE - NOT A WORD (.DOC or .RTF) FILE.  On a Windows PC, I recommend that you use Notepad to create this file.  On a MAC, you must use a suitable editor to create a plain text file.

 

Write a report that answers the following questions:

 

1. Why is it a good idea to choose names like plus and minus for the methods that perform polynomial arithmetic?

 

2.  Explain why you can pass an array of Polynomial objects to the Arrays.sort method which requires an array of Comparable objects?

 

3. Did you use the Dr Java debugger?  Was it useful and how did you use it?

 

4. Was it helpful to have the provided TestPolynomial class while writing the code in your Polynomial class?  How did you use it?

 

5.  Did the javadoc web pages for your Polynomial class and for the Arrays class help you to write your application class at the end?  How did you use them?

 

Turning in your Assignment:

 

Use the secure file transfer program to upload your Project1 folder containing your .java files, the Javadoc file for your Polynomial class and memo.txt file to your UNIX file directory: “account/cs210” where “account” is your account ID.  Do NOT get creative and change the name of the folder, the files, or upload them anywhere else but into your cs210 folder on the UNIX system.  You may get no credit if the grader can’t find them where they are supposed to be.

 

You must upload the files to our UNIX system before the posted deadline.  You will get no credit for late submissions.  Plan your time carefully so that you have enough time to upload your files.  If you have not finished, upload your files on time anyway - even if the program does not work correctly yet.  That way you are eligible for part credit on the assignment.  If you upload your files more than once, e.g. for backup, only the most recent copy will be saved.