8 Replies - 4536 Views - Last Post: 07 December 2008 - 04:01 AM Rate Topic: -----

#1 projeckt  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 15-November 08

Calculator using RPN

Post icon  Posted 04 December 2008 - 11:31 PM

Creating a calculator class that allows programs that use it to evaluate strings representing expressions in infix notation. Getting a no such element error right now. Anyone can point me in the right direction or if you see any additional errors please tell me.


public class Calculator {

  public static void main (String[] args) {
	  Calculator c = new Calculator();
	  double x = c.evaluate("5.5 + 3.4 + 2.0");
	  System.out.println("x = " +x+ ";");
		 }





  public Calculator() { }

	private static int precedence(String theOp) {
		if (theOp.equals("("))
			return 0;
		else if (theOp.equals("+") || theOp.equals("-"))
			return 1;
		else if (theOp.equals("*") || theOp.equals("/"))
			return 2;
		return -1;
	}

	private static void processOp (String theOp, Stack<String> opStack, Queue<String> result) {
		while ((! opStack.isEmpty()) && (precedence(theOp) <= precedence(opStack.first()))) {
			result.enqueue(opStack.pop());
		}
		opStack.push(theOp);
	}

	private static Queue<String> infixToPostfix(String infixStr) {
		Queue<String> result = new Queue<String>();
		Stack<String> opStack = new Stack<String>();
		int i = 0;
		while (i < infixStr.length()) {
			if (Character.isDigit(infixStr.charAt(i))) { // process constants
				String num_str = "";
				while (i < infixStr.length() && Character.isDigit(infixStr.charAt(i))) {
					num_str += infixStr.charAt(i++);
				}
				result.enqueue(num_str);
			} else {
				switch(infixStr.charAt(i++)) {
					case '(': opStack.push("(");
						break;
					case ')':
						while (opStack.first() != "(") {
							result.enqueue(opStack.pop());
						}
						opStack.pop();
						break;
					case '+': processOp("+", opStack, result);
						break;
					case '-': processOp("-", opStack, result);
						break;
					case '*': processOp("*", opStack, result);
						break;
					case '/': processOp("/", opStack, result);
						break;
				}
			}
		}
		while (! opStack.isEmpty()) {
			result.enqueue(opStack.pop());
		}
		return result;
	}



  private double evaluate(String expr) {
	Stack<String> exprStack = new Stack<String>();
	while(! expr.isEmpty()) {
	  String x = exprStack.pop();
  if (Character.isDigit(expr.charAt(0))) {
		 exprStack.push(x);
	  }
	  else {
		 int op2 = Integer.parseInt(exprStack.pop());
		 int op1 = Integer.parseInt(exprStack.pop());
		 int result = 0;
		 switch(expr.charAt(0))
		   {
			case '*': result = op1 * op2;
				break;
			case '+': result = op1 + op2;
				break;
			case '-': result = op1 - op2;
				break;
			case '/': result = op1 / op2;
				break;
			case '%': result = op1 % op2;
				break;
		   }
		 exprStack.push(x);
	  }
	}
	return Double.parseDouble(exprStack.pop());

  }







}

This post has been edited by projeckt: 04 December 2008 - 11:33 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Calculator using RPN

#2 Unknown Hero  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 17
  • View blog
  • Posts: 51
  • Joined: 04-September 07

Re: Calculator using RPN

Posted 05 December 2008 - 12:56 AM

I see one error here:
Stack<String> exprStack = new Stack<String>();
    while(! expr.isEmpty()) {
      String x = exprStack.pop();



You are trying to get element from an empty Stack.
Was This Post Helpful? 1
  • +
  • -

#3 projeckt  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 15-November 08

Re: Calculator using RPN

Posted 05 December 2008 - 03:40 AM

Hm. You are right. I want to pass the expression to it after the using the postfix, but it's of Queue type. Any suggestions?
Was This Post Helpful? 0
  • +
  • -

#4 Unknown Hero  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 17
  • View blog
  • Posts: 51
  • Joined: 04-September 07

Re: Calculator using RPN

Posted 05 December 2008 - 10:58 AM

Can you be more specific with what you have to do please?

Is this the program you have to do:
INPUT:
5 6 +
OUTPUT:
11
Was This Post Helpful? 0
  • +
  • -

#5 projeckt  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 15-November 08

Re: Calculator using RPN

Posted 05 December 2008 - 12:40 PM

Essentially, but the input that the user would give would be a normal arithmetic expression. The input would be
"5 + 6" which would be passed to the evaluate method. This expression would first be converted into RPN notation 5 6 +, then evaluated to 11.
Was This Post Helpful? 0
  • +
  • -

#6 projeckt  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 15-November 08

Re: Calculator using RPN

Posted 05 December 2008 - 06:57 PM

View Postprojeckt, on 5 Dec, 2008 - 11:40 AM, said:

Essentially, but the input that the user would give would be a normal arithmetic expression. The input would be
"5 + 6" which would be passed to the evaluate method. This expression would first be converted into RPN notation 5 6 +, then evaluated to 11.


exprStack.push(Queue.remove(infixToPostfix(expr)));

I believe that would help my problem. However, I am not too sure how to implement a class that uses the Queue interface to allow me to use the remove method.
Was This Post Helpful? 0
  • +
  • -

#7 projeckt  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 15-November 08

Re: Calculator using RPN

Posted 05 December 2008 - 08:04 PM

public class Calculator {

  public static void main (String[] args) {
	  Calculator c = new Calculator();
	  double x = c.evaluate("5.5 + 3.4 + 2.0");
	  System.out.println("x = " +x+ ";");
		 }

  public Calculator() { }

	private static int precedence(String theOp) {
		if (theOp.equals("("))
			return 0;
		else if (theOp.equals("+") || theOp.equals("-"))
			return 1;
		else if (theOp.equals("*") || theOp.equals("/"))
			return 2;
		return -1;
	}

	private static void processOp (String theOp, Stack<String> opStack, Queue<String> result) {
		while ((! opStack.isEmpty()) && (precedence(theOp) <= precedence(opStack.first()))) {
			result.enqueue(opStack.pop());
		}
		opStack.push(theOp);
	}

	private static Queue<String> infixToPostfix(String infixStr) {
		Queue<String> result = new Queue<String>();
		Stack<String> opStack = new Stack<String>();
		int i = 0;
		while (i < infixStr.length()) {
			if (Character.isDigit(infixStr.charAt(i))) { // process constants
				String num_str = "";
				while (i < infixStr.length() && Character.isDigit(infixStr.charAt(i))) {
					num_str += infixStr.charAt(i++);
				}
				result.enqueue(num_str);
			} else {
				switch(infixStr.charAt(i++)) {
					case '(': opStack.push("(");
						break;
					case ')':
						while (opStack.first() != "(") {
							result.enqueue(opStack.pop());
						}
						opStack.pop();
						break;
					case '+': processOp("+", opStack, result);
						break;
					case '-': processOp("-", opStack, result);
						break;
					case '*': processOp("*", opStack, result);
						break;
					case '/': processOp("/", opStack, result);
						break;
				}
			}
		}
		while (! opStack.isEmpty()) {
			result.enqueue(opStack.pop());
		}
		return result;
	}



  private double evaluate(String expr) {
   Queue<String> r = infixToPostfix(expr);
	Stack<String> exprStack = new Stack<String>();
	exprStack.push(r.dequeue());
	while(! expr.isEmpty()) {
	  String x = exprStack.pop();
  if (Character.isDigit(expr.charAt(0))) {
		 exprStack.push(x);
	  }
	  else {
		 int op2 = Integer.parseInt(exprStack.pop());
		 int op1 = Integer.parseInt(exprStack.pop());
		 int result = 0;
		 switch(expr.charAt(0))
		   {
			case '*': result = op1 * op2;
				break;
			case '+': result = op1 + op2;
				break;
			case '-': result = op1 - op2;
				break;
			case '/': result = op1 / op2;
				break;
			case '%': result = op1 % op2;
				break;
		   }
		 exprStack.push(x);
	  }
	}
	return Double.parseDouble(exprStack.pop());

  }

}


Changed it so that the postfixed expression is passed to the empty stack. Now it's running in an infinite loop. Any suggestions?
Was This Post Helpful? 0
  • +
  • -

#8 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8327
  • View blog
  • Posts: 31,857
  • Joined: 06-March 08

Re: Calculator using RPN

Posted 05 December 2008 - 10:33 PM

I don't see why you take care of parenthesis () RPN calculator do not need them... and actually none of them has parenthesis on their "keyboard"
Was This Post Helpful? 0
  • +
  • -

#9 projeckt  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 15-November 08

Re: Calculator using RPN

Posted 07 December 2008 - 04:01 AM

I got to the program to work on some base cases. The only problem I have now is it won't process decimals. It just ignores them all together. For example, if you look in the main, the y string would be processed as 0 5 2 0 3 1 6 2 / + * 2 25 -. Any suggestions for actually processing decimal numbers?

import java.util.*;


 public class Calculator  {
	public static void main (String[] args) {
		Calculator c = new Calculator();
		double x = c.evaluate("0 / 5");
		double y = c.evaluate("0.5 * (2.0 + 3.1/6.2) - 2.25");
		System.out.println("x = " +x+"; y = "+y);
	}

	public Calculator() {
	}

	private static int precedence(String theOp) {
		if (theOp.equals("("))
			return 0;
		else if (theOp.equals("+") || theOp.equals("-"))
			return 1;
		else if (theOp.equals("*") || theOp.equals("/"))
			return 2;
		return -1;
	}

	private static void processOp (String theOp, Stack<String> opStack, Queue<String> result) {
		while ((! opStack.isEmpty()) && (precedence(theOp) <= precedence(opStack.first()))) {
			result.enqueue(opStack.pop());
		}
		opStack.push(theOp);
	}

	private static Queue<String> infixToPostfix(String infixStr) {
		Queue<String> result = new Queue<String>();
		Stack<String> opStack = new Stack<String>();
		int i = 0;
		while (i < infixStr.length()) {
			if (Character.isDigit(infixStr.charAt(i))) { // process constants
				String num_str = "";
			  while (i < infixStr.length() && Character.isDigit(infixStr.charAt(i))) {
					num_str += infixStr.charAt(i++);
				}
				result.enqueue(num_str);
			} else {
				 switch(infixStr.charAt(i++)) {
					 case '(': opStack.push("(");
						break;
					 case ')':
						while (opStack.first() != "(") {
							result.enqueue(opStack.pop());
						}
						opStack.pop();
						break;
					 case '+': processOp("+", opStack, result);
						break;
					 case '-': processOp("-", opStack, result);
						break;
					 case '*': processOp("*", opStack, result);
						break;
					 case '/': processOp("/", opStack, result);
						break;
				 }
			  }
		}
		while (! opStack.isEmpty()) {
			result.enqueue(opStack.pop());
		}
		return result;
	}

	private double evaluate(String expr) {
		Queue<String> r = infixToPostfix(expr);
		Stack<String> exprStack = new Stack<String>();
		double value;
		String temp = "";
		while (! r.isEmpty()) {
			temp = temp + " "+ r.dequeue();
	 }
		System.out.println(temp);
		StringTokenizer postfix = new StringTokenizer(temp);
		String x;
		while (postfix.hasMoreTokens()) {
			 x = postfix.nextToken();
			 if (Character.isDigit(x.charAt(0))) {
				 exprStack.push(x);
			 } else {
				 double op2 = Double.parseDouble(exprStack.pop());
				 double op1 = Double.parseDouble(exprStack.pop());
				 double result = 0;
				 switch(x.charAt(0)) {
					case '*': result = op1 * op2;
					   break;
					case '+': result = op1 + op2;
					   break;
					case '-': result = op1 - op2;
					   break;
				   case '/':
					//   if op1 || op2 == 0) {
					//   throw new IllegalArgumentException("Operands cannot be zero while dividing.");
		   //			} else {
						 result = op1 / op2;
			 //		  }
						  break;
					case '%': result = op1 % op2;
					   break;
				 }
				String y = Double.toString(result);
				exprStack.push(y);
			 }
		}
		value = Double.parseDouble(exprStack.pop());
		return value;
	}
 }

This post has been edited by projeckt: 07 December 2008 - 04:03 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1