Mega Code Archive

 
Categories / Java / Collections Data Structure
 

Reverse Polish Notation

//package rpn; import java.util.Stack; import java.util.Scanner; /**  * ReversePolishNotation is a simple application which will test several RPN  * equations to make sure the calcRPN method works properly.  *   * @author Alex Laird  * @version 1.0 File: ReversePolishNotation.java Created: Oct 2008  */ public class ReversePolishNotation {   /**    * This method tests whether the calculated answer is within the acceptable    * bounds of the actual answer to be correct.    *     * @param actAnswer    *            is the correct answer to the RPN equation    * @param calcAnswer    *            is the calculated answer to the RPN from calcRPN    */   public static void checkPrecision(Double actAnswer, Double calcAnswer) {     if (Math.abs(calcAnswer - actAnswer) < 0.000001) {       return;     } else {       System.out           .println("The calculated answer was not within 0.000001 of the actual answer.");     }   }   /**    * This method tests to see whether the value of a String is a legal RPN    * mathematical operator or not.    *     * @param next    *            is the value to be tested    * @return whether the next value is a mathematical operator or not    */   public static boolean nextIsOperator(String next) {     return (next.equals("+") || next.equals("-") || next.equals("*") || next         .equals("/"));   }   /**    * This method will calculate the answer of the given Reverse Polar Notation    * equation. All exceptions are thrown to the parent for handling.    *     * @param input    *            is the equation entered by the user    * @throws EmptyRPNException    *             when there is no RPN equation to be evaluated.    * @throws RPNDivideByZeroException    *             when the RPN equation attempts to divide by zero.    * @throws RPNUnderflowException    *             when the RPN equation has a mathematical operator before    *             there are enough numerical values for it to evaluate.    * @throws InvalidRPNException    *             when the RPN equation is a String which is unable to be    *             manipulated.    * @throws RPNOverflowException    *             when the RPN equation has too many numerical values and not    *             enough mathematical operators with which to evaluate them.    * @return the top item of the stack; the calculated answer of the Reverse    *         Polish Notation equation    */   public static double calcRPN(String input) {     // eliminate any leading or trailing whitespace from input     input = input.trim();     // scanner to manipulate input and stack to store double values     String next;     Stack<Double> stack = new Stack<Double>();     Scanner scan = new Scanner(input);     // loop while there are tokens left in scan     while (scan.hasNext()) {       // retrieve the next token from the input       next = scan.next();       // see if token is mathematical operator       if (nextIsOperator(next)) {         // ensure there are enough numbers on stack         if (stack.size() > 1) {           if (next.equals("+")) {             stack.push((Double) stack.pop() + (Double) stack.pop());           } else if (next.equals("-")) {             stack.push(-(Double) stack.pop() + (Double) stack.pop());           } else if (next.equals("*")) {             stack.push((Double) stack.pop() * (Double) stack.pop());           } else if (next.equals("/")) {             double first = stack.pop();             double second = stack.pop();             if (first == 0) {               System.out                   .println("The RPN equation attempted to divide by zero.");             } else {               stack.push(second / first);             }           }         } else {           System.out               .println("A mathematical operator occured before there were enough numerical values for it to evaluate.");         }       } else {         try {           stack.push(Double.parseDouble(next));         } catch (NumberFormatException c) {           System.out               .println("The string is not a valid RPN equation.");         }       }     }     if (stack.size() > 1) {       System.out           .println("There too many numbers and not enough mathematical operators with which to evaluate them.");     }     return (Double) stack.pop();   }   /**    * The main method from which the program executes; it handles all testing    * and exception handling.    *     * @param args    *            unused    */   public static void main(String[] args) {     String[] equations = new String[8];     Double[] answers = new Double[8];     double answer = 0.0;     // this equation will pass     equations[0] = "23.3 5 16.2 + 8 * -";     // this equation will fail with an EmptyRPNException     equations[1] = null;     // this equation will fail with an EmptyRPNException     equations[2] = "   ";     // this equation will fail with an InvalidRPNException     equations[3] = "Hello world!";     // this equation will fail with a RPNUnderflowException     equations[4] = "12 * 3 15 18.723 - + 52 /";     // this equation will fail with a RPNDivideByZeroException     equations[5] = "52.2 12 + 17 - 9.7 10 0 / + -";     // this equation will fail with a RPNOverflowException     equations[6] = "12.2 17 / 33.333 - 12";     // this equation will pass     equations[7] = "2 3 / 3 2 / *";     answers[0] = -146.3;     answers[7] = 1.0;     // loop until all test values evaluated     for (int i = 0; i < equations.length; i++) {       System.out.println("Equation #" + (i + 1) + ": " + equations[i]           + ".");       // call method to calculate answer       answer = calcRPN(equations[i]);       // ensure that the calculated answer is within 0.000001 of the       // actual answer       checkPrecision(answers[i], answer);       System.out.println("Passed! The calculated value of "           + equations[i] + " is " + answer + ".\n");     }   } }