Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

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 variable x. The expression can use the operators +, -, *, /, and ^, where ^ represents the operation of raising a number to a power. It can use mathematical functions such as sin, cos, abs, and ln. See the source code file for full details. The Expr class 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 an Expr object defined by a given expression. The parameter, def, is a string that contains the definition. For example, new Expr("x^2") or new Expr("sin(x)+3*x"). If the parameter in the constructor call does not represent a legal expression, then the constructor throws an IllegalArgumentException. The message in the exception describes the error.

If func is a variable of type Expr and num is of type double, then func.value(num) is a function that returns the value of the expression when the number num is substituted for the variable x in the expression. For example, if Expr represents the expression 3*x+1, then func.value(5) is 3*5+1, or 16. If the expression is undefined for the specified value of x, then the special value Double.NaN is 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 of x, print a message to that effect. You can use the boolean-valued function Double.isNaN(val) to check whether a number, val, is Double.NaN.

The user should be able to enter as many values of x as 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 numbers

Converting the input line into an object of type Expr involves calling the constructor from the Expr class. This call might generate an IllegalArgumentException. The algorithm must be expanded to handle this exception and print an error message if it occurs. When an error occurs, I use a continue statement 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 numbers

The last step, reading and processing the user's numbers, expands into a loop, which is nested inside the main while loop. In this loop, I could use TextIO.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 type double. 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 by TextIO. The conversion from a string, line, to a double is done using a method that was introduced in Section 7.4. The conversion will generate a NumberFormatException if 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 x = Double.parseDouble(line)
              }
              catch (NumberFormatException e) {
                 Print an error message
                 continue
              }
              Let val = expression.value(x)
              if val is Double.NaN:
                 Print an error message
              else:
                 Output val

All 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 {
                   x = Double.parseDouble(line);
                }
                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 ]

 
 
  Published under free license. Design by Interspire