• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

Help with calculator (determining order of operations) *Java*

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.

iLoki

Member
Joined
Dec 8, 2008
Hey guys,
I am in the process of re-teaching myself java, and as a way to solidify stacks in my brain (never really understood them till yesterday pretty much... kicked myself after I realized how nice and simple they are) I am creating a calculator. At the moment, it can function as a standard (12 + 6) or post script (12 6 +) calculator, and can handle many, many operands and operators.

The issue I'm currently working with is a method of determining/enforcing the order of operations. (Please Excuse My Dear Aunt Sallie) and all that. Eventually I'm going to work on turning this into a simple GUI calculator.

The application, as it stands, supports addition, subtraction, multiplication and division. I plan to add a method for exponents as well.

Here's my code:
Code:
  /**@Author: J. Carter
  	 *@Date: 6/25/09
	 *This started as an RPN calculator ( 12 5 + is equal to 12 + 5), however it can handle both standard 
	 *(although not in the proper order) and RPN notations. Error checking built in to make sure the user
	 *enters valid input, will notify of invalid input and reprompt.
  	 */
   import java.util.*;

    public class rpnCalc
   {
       public static void main(String[] Args)
      {
         String str;
         String[] tokens;
         double result;
         Stack<Double> operands = new Stack();
         Stack<String> operators = new Stack();
         Scanner kb = new Scanner(System.in);
      //initialize varables
         str = "";
         result = 0;
      	
         System.out.print("Enter a simple expression,\nSeparate pieces with a space, example: 12 + 96, or 12 96 + \nPress q to exit\n");
         System.out.println("All expressions are evaluated from RIGHT to LEFT.");
         while(!str.equals("q"))
         { 
            str = kb.nextLine();
            tokens = str.split("\\s+");
         
            fillStacks(operands,operators,tokens);
            
            result = calculate(operands,operators);
            
            System.out.println(result + "\nAnother Expression? (q to quit)"); 
         } // end while
         System.out.println("Thanks! Bye now!");      
      }//end main
    	
   /** Methods for Addition, Subtraction, Multiplication and Division */
       private static double add(Stack<Double> stk)
      {
         double op2 = stk.pop();
         double op1 = stk.pop();
         double result = op1 + op2;
         stk.push(result);
         return result;
      }// end add
      
       private static double subtract(Stack<Double> stk)
      {
         double op2 = stk.pop();
         double op1 = stk.pop();
         double result = op1 - op2;
         stk.push(result);
         return result;
      }// end subtract
      
       private static double divide(Stack<Double> stk)
      {
         double op2 = stk.pop();
         double op1 = stk.pop();
         double result = op1 / op2;
         stk.push(result);
         return result;
      }//end divide
   	
       private static double multiply(Stack<Double> stk)
      {
         double op2 = stk.pop();
         double op1 = stk.pop();
         double result = op1 * op2;
         stk.push(result);
         return result;
      }//end multiply
   	/**Method for error checking user input. If parseInt fails, this method is invoked, and determines whether input is invalid,
   	or an operator.*/
       public static boolean isOperator(String str)
      {
         boolean tf;
         if(str.equals("+") || str.equals("-") || str.equals("/") || str.equals("*"))
            tf = true;
         else if(str.equals("q") || str.equals("Q"))
            tf = false;
         else
         {	
            tf = false;
            System.out.println("Invalid input. Please try again.");
         }
         return tf;
      }//end isOperator
      /**Methods for filling stacks and evaluating expressions.*/
       private static void fillStacks(Stack<Double> stkd, Stack<String> stks,String[] str)
      {
         boolean isOp;
      	
         for(int i = 0; i < str.length; i++)
         {
            try
            {
               stkd.push(Double.parseDouble(str[i]));
            }//end try
                catch (NumberFormatException e)
               {
                  isOp = isOperator(str[i]);
                  if(isOp == true)
                     stks.push(str[i]);
               }//end catch
         }//end for
      }//end fillStacks
      
   	/**perform calculations based on operators, loop until operator stack is empty*/
       private static double calculate(Stack<Double> stkd, Stack<String> stks)
      {
         double result = 0;
         String str = "";
      	
         while(!stks.empty())  
         {
            str = stks.pop();
            if(str.equals("+"))
               result = add(stkd);
            else if(str.equals("-"))
               result = subtract(stkd);
            else if(str.equals("/"))
               result = divide(stkd);
            else if(str.equals("*"))
               result = multiply(stkd);
         }//end while
         return result;
      }end calculate	
   }//end rpnCalc
 
Don't think orders of operations using stacks for regular input is probably not going to work well - you need to be able to look ahead, and so the benefits of a stack are lost. I think.

On the other hand, postfix should be pretty straightforward. Push stuff onto the stack until reaching an operator, then perform that operation on the previous two numbers and push the result back on the stack, continue. Your code already does this :p

So 123*+ (aka 1+2*3) would evaluate correctly.
 
Ok, I'm already tokenizing my input using split(), I can try to switch from stacks to linked lists (probalbly doubly linked, although I think a single link would work ok) as that would allow me to search operators and allow me to perform more complex expressions, as I could establish a hierarchy and allow the use of standard notation with correct evaluation patterns.

for example, the code as is, will return 12 + 6 * 9 as 162, instead of the proper answer: 66. If I turn this into a GUI calculator similar to the built in windows calculator, then I could fore go the need to establish the order of operations, as the user would be forced to enter their operands 1 pair at a time to perform the operations correctly.
 
Back