ReversePolishNotation.java Source code

Java tutorial

Introduction

Here is the source code for ReversePolishNotation.java

Source

//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");
        }
    }
}