CS110 Project 1

Bob Wilson

We want to write and test a program for solving a quadratic equation of the form:

a x2 + b x + c = 0

for values of x that make the equation true.  These are called the root(s) of the equation.

Fortunately, there is a formula that gives us values of x for the coefficients a, b, and c:

x = (-b + square root (b2 – 4ac))/2a

We can use this formula as part of the algorithm in our program to solve quadratic equations.  An algorithm defines the steps in logic and calculation used for solving a problem.

As we discussed in Lecture 5, the textbook’s program for solving quadratic equations is deficient.  It merely takes the three values entered for the coefficients a, b, and c, and uses them as variables in an expression based on the formula.  There are cases where the calculation of the expression is impossible because some law of Mathematics is violated such as trying to take the square root of a negative number or trying to divide by zero.  The textbook program was not written to handle these cases because the concept of flow of control and Boolean logic had not been introduced to you yet.  However, a complete algorithm for solving quadratic equations must include needed logic decisions based on the input values as well as calculations using formulas.

Now that we have introduced the concept of logic decisions based on the if statement and the else clause, you have the knowledge that you need to write a better program for solving quadratic equations.  Naturally, your program must properly select and execute the correct calculation for any supplied values of a, b, and c.  However, here are six test cases that each force your program to select one of the six different possible calculations with the format of the solution that your program should provide for that case.

 Value for a Value for b Value for c Solution for some possible test cases Should return exactly this string in each case! 1 0 -3 Root 1 is 1.7320508075688772 Root 2 is -1.7320508075688772 1 1 1 Root 1 is -0.5 + i * 0.8660254037844386 Root 2 is -0.5 - i * 0.8660254037844386 1 2 1 The only root is -1.0 0 2 4 The only root is -2.0 0 0 6 No value for x is a solution 0 0 0 Any value for x is a solution

As described in Lecture 5, we have factored our solution into two classes:

A QuadraticCLI class that handles all the user input and output

A QuadraticSolver class the handles all the logic decisions and calculations

You can get the beginning project files by downloading and unzipping the following file Project1.zip.  You will be adding your code to one of the Java files in this project. Here are some things to consider:

Overall:

You must write comments in your code to document the design of your program.  For this assignment, these comments must be written using the Java style single line comment by beginning a comment line with // or putting // and a comment at the end of a line of code.  At a minimum, you must have a block of comments for each class and for each method in a class.  Try to make these comments useful to the programmer who will be reading them and not just an English re-statement of the contents of the line(s) of code.

You should read the Quadratic CLI source code to understand what it is doing, but you will not need to modify it.

1.  QuadraticCLI contains the main method that is the starting point for the execution of your program.  You need to configure the Dr Java project configuration with the name of the class that contains the main method (QuadraticCLI) to run your program.

2.  Notice that there are no calculations done in the QuadraticCLI class.  The code in QuadraticCLI just stores the values of the coefficients.   This class instantiates a Scanner object, uses the Scanner object to get the coefficient values, passes these values as arguments to the appropriate methods of the QuadraticSolver class, and prints the Strings returned by the QuadraticSolver class’s getEquation and getSolution methods.

Notice how the QuadraticCLI class asks the user a yes/no question and makes a decision based on the response.  It prompts the user with a question and uses the Scanner method getNext to get a String input, uses a Boolean logic expression as the condition for the loop to check the response for equality with an expected response such as “yes” or “y”, and controls the flow of the program based on the condition.  Note: The code uses the charAt method of the String response from scan.next() to get the first (zeroth) character and checks that character for equality (==) with the character literal ‘y’.

Also, notice which statements need to be re-executed and which do not.  It does not need to re-execute the creation of the Scanner object.  Therefore, it does not include that statement inside the scope of the loop.

1. The QuadraticSolver class does not need to have a main method.

2.  The QuadraticSolver class should not use any System.out.println or any Scanner methods.  It gets the values of the coefficients via parameters in its method calls.  Its getEquation and getSolution methods provide a String object as their return values.  The caller (e.g. QuadraticCLI) takes responsibility for displaying those strings to the user in some way that is not known to the QuadraticSolver class.  Because we have not programmed any user input or output functions in the QuadraticSolver class, we can reuse our QuadraticSolver code with a different type of user interface class such as a GUI instead of a CLI at another time.

3. In the logic that you program, you should try to use the minimal number of logic checks to determine which version of the solution your code must calculate and return.  This will make your program easier to read than if you use repetitive decision logic steps.  You should use nested if-else statements to minimize the number of times that your code evaluates Boolean expressions.  Before writing the code, think about a logical order for your code to make the needed flow of control decisions.  Also, your code should not calculate the value of the discriminant until the flow of control logic determines that the value will be needed. This avoids wasting time on unneeded computations.

4. When we calculate the discriminant, we want to create an int value so that we can evaluate boolean expressions using >, <, and/or ==.  Use the expression b*b - 4*a*c to calculate the discriminant and produce an int value rather than the Math.pow method which produces a double value.  If you calculate the discriminant as an integer, then you can make Boolean decisions based on the value of the discriminant == 0 without concern for a double value being almost equal to zero but not quite zero.

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 project 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.  This is 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.

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 “result” in the first line of the Watch section and you should see the text of the String result about to be returned by the method.  If you are trying this experiment on the original code that I supplied, the value of result should be “null” as set by the first line of code that I provided in that method.  If you have already added your code for calculating the result String, you should see the value that your code has calculated based on the values of a, b, and c.

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.

Explain in your own words your strategy for the design of the QuadraticSolver decision logic.  Did you consider any other ways to do it?  Why did you choose to do it the way you finally did it?

Did you benefit from using the DrJava debugger and, if so, how?