## Solution for

Programming Exercise 9.4

THIS PAGE DISCUSSES ONE POSSIBLE SOLUTION to the following exercise from this on-line Java textbook.

Exercise 9.4:The file Expr.java defines a class,Expr, that can be used to represent mathematical expressions involving the variablex. The expression can use the operators +, -, *, /, and ^, where ^ represents the operation of raising a number to a power. It can use mathematical functions such assin,cos,abs, andln. See the source code file for full details. TheExprclass uses some advanced techniques which have not yet been covered in this textbook. However, the interface is easy to understand. It contains only a constructor and two public methods.The constructor

new Expr(def)creates anExprobject defined by a given expression. The parameter,def, is a string that contains the definition. For example,new Expr("x^2")ornew Expr("sin(x)+3*x"). If the parameter in the constructor call does not represent a legal expression, then the constructor throws anIllegalArgumentException. The message in the exception describes the error.If

funcis a variable of typeExprandnumis of typedouble, thenfunc.value(num)is a function that returns the value of the expression when the numbernumis substituted for the variablexin the expression. For example, ifExprrepresents the expression3*x+1, thenfunc.value(5)is3*5+1, or 16. If the expression is undefined for the specified value ofx, then the special valueDouble.NaNis returned.Finally,

func.getDefinition()returns the definition of the expression. This is just the string that was used in the constructor that created the expression object.For this exercise, you should write a program that lets the user enter an expression. If the expression contains an error, print an error message. Otherwise, let the user enter some numerical values for the variable

x. Print the value of the expression for each number that the user enters. However, if the expression is undefined for the specified value ofx, print a message to that effect. You can use theboolean-valued functionDouble.isNaN(val)to check whether a number,val, isDouble.NaN.The user should be able to enter as many values of

xas desired. After that, the user should be able to enter a new expression. Here is an applet that simulates my solution to this exercise, so that you can see how it works:

Discussion

A pseudocode algorithm for the program is given by:

while (true): Get a line of input from the user if the line is empty: break Convert the input line to an Expr Read and process the user's numbersConverting the input line into an object of type

Exprinvolves calling the constructor from theExprclass. This call might generate anIllegalArgumentException. The algorithm must be expanded to handle this exception and print an error message if it occurs. When an error occurs, I use acontinuestatement to jump back to the start of the loop without reading any numbers from the user:while (true): Get a line of input from the user if the line is empty: break try { Let expression = new Expr(line) } catch (IllegalArgumentException e) { Print an error message continue // jumps back to start of loop } Read and process the user's numbersThe last step, reading and processing the user's numbers, expands into a loop, which is nested inside the main

whileloop. In this loop, I could useTextIO.getDouble()to read one of the user's numbers, but instead I choose to read the user's input into a string and convert that string into a value of typedouble. This has two advantages: I can end the loop when the user presses return. And I can do nicer error handling than the default error-handling that is provided byTextIO. The conversion from a string,line, to adoubleis done using a method that was introduced in Section 7.4. The conversion will generate aNumberFormatExceptionif the user's input is not a legal number. The algorithm for reading and processing the user's numbers becomes:while (true): Get a line of input from the user if the line is empty: break try { Let d = new Double(line) Let x = d.doubleValue() } catch (NumberFormatException e) { Print an error message continue } Let val = expression.value(x) if val is Double.NaN: Print an error message else: Output valAll this can be easily translated into the complete solution, which follows.

The Solution

public class FunctionEvaluator { public static void main(String[] args) { String line; // A line of input read from the user. Expr expression; // The definition of the function f(x). double x; // A value of x for which f(x) is to be calculated. double val; // The value of f(x) for the specified value of x. TextIO.putln("This program will evaluate a specified function, f(x), at"); TextIO.putln("specified values of the variable x. The definition of f(x)"); TextIO.putln("can use the operators +, -, *, /, and ^ as well as mathematical"); TextIO.putln("functions such as sin, abs, and ln."); while (true) { /* Get the function from the user. A line of input is read and used to construct an object of type Expr. If the input line is empty, then the loop will end, and the program will terminate. */ TextIO.putln("\n\n\nEnter definition of f(x), or press return to quit."); TextIO.put("\nf(x) = "); line = TextIO.getln().trim(); if (line.length() == 0) break; try { expression = new Expr(line); } catch (IllegalArgumentException e) { // An error was found in the input. Print an error // message and go back to the beginning of the loop. TextIO.putln("Error! The definition of f(x) is not valid."); TextIO.putln(e.getMessage()); continue; } /* Read values of x from the user, until the user presses return. If the user's input is not a legal number, print an error message. Otherwise, compute f(x) and print the result. */ TextIO.putln("\nEnter values of x where f(x) is to be evaluated."); TextIO.putln("Press return to end."); while (true) { TextIO.put("\nx = "); line = TextIO.getln().trim(); if (line.length() == 0) break; try { Double d = new Double(line); x = d.doubleValue(); } catch (NumberFormatException e) { TextIO.putln("\"" + line + "\" is not a legal number."); continue; } val = expression.value(x); if (Double.isNaN(val)) TextIO.putln("f(" + x + ") is undefined."); else TextIO.putln("f(" + x + ") = " + val); } // end while } // end while TextIO.putln("\n\n\nOK. Bye for now."); } // end main(); } // end class FunctionEvaluator

[ Exercises | Chapter Index | Main Index ]