Prefix expression to evaluate multiple expressions simultaneously - java

private class InputListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Stack<Integer> operandStack = new Stack<Integer>();
Stack<Character> operatorStack = new Stack<Character>();
String input = inputTextField.getText();
StringTokenizer strToken = new StringTokenizer(input, " ", false);
while (strToken.hasMoreTokens())
{
String i = strToken.nextToken();
int operand;
char operator;
try
{
operand = Integer.parseInt(i);
operandStack.push(operand);
}
catch (NumberFormatException nfe)
{
operator = i.charAt(0);
operatorStack.push(operator);
}
}
int result = sum (operandStack, operatorStack);
resultTextField.setText(Integer.toString(result));
}
My prefix expression code will only evaluate one expression at a time (i.e. + 3 1). I want it to evaluate multiple expressions in one user-input expression (i.e. * + 16 4 + 3 1). How can I edit the code provided to make it evaluate multiple expressions? Thank you for your help.

To simply make your program do a bit more you can use a loop to keep operating on the operandStack and pushing the result of the previous result to the stack. I left my println statements in so you can see what its doing. Also I modified your method so it can sit inside a standalone main method.
You should look into the Shunting-yard algorithm, its quite fun to implement and it is somewhat like what your doing here. http://en.wikipedia.org/wiki/Shunting-yard_algorithm
public static void main(String[] args) {
Stack<Integer> operandStack = new Stack<Integer>();
Stack<Character> operatorStack = new Stack<Character>();
String input = "12 + 13 - 4";
StringTokenizer strToken = new StringTokenizer(input, " ", false);
while (strToken.hasMoreTokens()) {
String i = strToken.nextToken();
int operand;
char operator;
try {
operand = Integer.parseInt(i);
operandStack.push(operand);
} catch (NumberFormatException nfe) {
operator = i.charAt(0);
operatorStack.push(operator);
}
}
// loop until there is only 1 item left in the operandStack, this 1 item left is the result
while(operandStack.size() > 1) {
// some debugging println
System.out.println("Operate\n\tbefore");
System.out.println("\t"+operandStack);
System.out.println("\t"+operatorStack);
// perform the operations on the stack and push the result back onto the operandStack
operandStack.push(operate(operandStack, operatorStack));
System.out.println("\tafter");
System.out.println("\t"+operandStack);
System.out.println("\t"+operatorStack);
}
System.out.println("Result is: " + operandStack.peek());
}
/**
* Performs math operations and returns the result. Pops 2 items off the operandStack and 1 off the operator stack.
* #param operandStack
* #param operatorStack
* #return
*/
private static int operate(Stack<Integer> operandStack, Stack<Character> operatorStack) {
char op = operatorStack.pop();
Integer a = operandStack.pop();
Integer b = operandStack.pop();
switch(op) {
case '-':
return b - a;
case '+':
return a + b;
default:
throw new IllegalStateException("Unknown operator '"+op+"'");
}
}
I left the operate method (previously called sum) as close to what you had it as possible, however I think that your code could be improved by simply passing 2 integers and a operator to the function. Making the function alter your stacks isnt a great thing and could lead to confusing problems.
Consider making your method signature this instead:
private static int operate(Integer a, Integer b, char operator) {
switch(operator) {
case '-':
return b - a;
case '+':
return a + b;
default:
throw new IllegalStateException("Unknown operator '"+operator+"'");
}
}
and then popping from the stack and passing those to the method. Keeping your stack altering code all in one place.
operandStack.push(operate(operandStack.pop(), operandStack.pop(), operatorStack.pop()));

Related

Java: Stacks expression evaluator: empty stack exception when subtracting or multiplying

This is somewhat of a loaded question. I'm writing a Lisp evaluator algorithm which takes input expressions written, for example, as:
(+ (- 6) (* 2 3 4) (/ (+ 3) (*) (- 2 3 1)))
The problem is: it throws an EmptyStack error because of the operations
(- 6) and (*)
When I write it as (- 0 6) and (* 1) it compiles correctly with the correct result. I think it is looking to subtract FROM something, and multiply something (can't have no digits). It has something to do with the structure of my operand evaluation. I want to implement this into the program itself, without having to manually add zeros for subtraction and one's for multiplication. Any ideas on how to go doing this?
I've been staring at it all day and can't seem to figure out why my push/pop structure acts up in this way. I tried experimenting with regex, but that did not seem to do the trick.
Program structure:
1) Uses two stacks: expressionStack of type Object, and currentOperationStack of type Double.
2) evaluateCurrentOperation() method evaluates the current operation:
Pops operands from expressionStack and pushes them onto currentOperationStack until it finds an operator.
Uses the operator on the operands on currentOperationStack.
Pushes the result into expressionStack.
3) evaluate() method evaluates the current Lisp expression in inputExpression (using a scanner to read, and case statements for operands) and returns the result.
import java.util.*;
public class LispEvaluator {
/**
* Input expression
*/
private String inputExp;
/**
* Stacks created for the main expression and current operation.
*/
private Stack<Object> expStack;
private Stack<Double> currentOpStack;
/**
* Default constructor initializes input and creates Stack objects.
*/
public LispEvaluator()
{
inputExp = "";
expStack = new Stack<Object>();
currentOpStack = new Stack<Double>();
}
/**
* Constructor sets inputExpr to inputExpression and creates Stack objects.
* #param inputExpression
* #throws LispEvaluatorException
*/
public LispEvaluator(String input_Expression) throws LispEvaluatorException
{
// If there is no expression, throws an exception.
if(input_Expression == null)
{
throw new LispEvaluatorException("Input statement is null.");
}
// Objects created
inputExp = input_Expression;
expStack = new Stack<Object>();
currentOpStack = new Stack<Double>();
}
/**
* evaluateCurrentOperation() method evaluates the current operation:
* - Pops operands from expStack and pushes them onto currentOpStack until it finds an operator.
* - Uses the operator on the operands on currentOpStack.
* - Pushes the result into exprStack.
*/
private void evaluateCurrentOperation()
{
String current_Operation;
boolean numeric = true;
// Do... while statement sets current operation (while it is numeric).
do{
current_Operation = (String.valueOf(expStack.pop()));
try{
Double number = Double.parseDouble(current_Operation);
currentOpStack.push(number);
}catch(NumberFormatException nfe){
numeric = false;
}
} while(numeric);
double result;
switch (current_Operation) {
case "*":
result = currentOpStack.pop();
while(!currentOpStack.isEmpty()){
result *= currentOpStack.pop();
}
break;
case "/":
result = currentOpStack.pop();
while(!currentOpStack.isEmpty()){
result /= currentOpStack.pop();
}
break;
case "+":
result = currentOpStack.pop();
while(!currentOpStack.isEmpty()){
result += currentOpStack.pop();
}
break;
case "-":
result = currentOpStack.pop();
while(!currentOpStack.isEmpty()){
result -= currentOpStack.pop();
}
break;
default:
result = currentOpStack.pop();
break;
}
expStack.push(result);
}
/**
* evaluate() method evaluates the current Lisp expression in inputExpr and returns the result.
* #throws LispEvaluatorException
*/
public double evaluate() throws LispEvaluatorException
{
Scanner inputExprScanner = new Scanner(inputExp);
/**
* Breaks the string into single characters using a delimiter.
*/
inputExprScanner = inputExprScanner.useDelimiter("\\s*");
/**
* Scans the tokens in the string (runs while there is a next token).
*/
while (inputExprScanner.hasNext())
{
/**
* If it has an operand, pushes operand object onto the exprStack.
*/
if (inputExprScanner.hasNextInt())
{
/**
* Scanner gets all of the digits (regular expression \\d+ means any digit).
*/
String dataString = inputExprScanner.findInLine("\\d+");
expStack.push(Double.parseDouble(dataString));
}
else
{
/**
* Gets one character in String token.
*/
String token = inputExprScanner.next();
char item = token.charAt(0);
switch(item)
{
// If "(", next token is an operator (so do nothing).
case '(':
break;
// If ")", it will evaluate that expression since parenthesis are closed.
case ')':
evaluateCurrentOperation();
break;
// If there is an operator "* + / -", then it pushes the operator onto exprStack.
case'*':
expStack.push("*");
break;
case'+':
expStack.push("+");
break;
case'/':
expStack.push("/");
break;
case'-':
expStack.push("-");
break;
/**
* Default throws an error.
*/
default:
throw new LispEvaluatorException(item + " is not a valid operator");
} // end switch
} // end else
} // end while
/**
* If you run out of tokens, the value on the top of exprStack is the result of the expression.
*
*/
return Double.parseDouble(String.valueOf(expStack.pop()));
}
/**
* Reset method sets inputExpr to inputExpression and clears Stack objects.
* #param inputExpression
* #throws LispEvaluatorException
*/
public void reset(String inputExpression) throws LispEvaluatorException
{
if(inputExpression == null)
{
throw new LispEvaluatorException("Input statement is null");
}
inputExp = inputExpression;
expStack.clear();
currentOpStack.clear();
}
/**
* Test method to print the result of the expression evaluator.
* #param s
* #param expr
* #throws LispEvaluatorException
*/
private static void evaluateExprTest(String s, LispEvaluator expr) throws LispEvaluatorException
{
Double result;
System.out.println("Expression: " + s);
expr.reset(s);
result = expr.evaluate();
System.out.printf("Result: %.2f\n", result);
System.out.println("-------");
}
/**
* Main method uses test cases to test the evaluator.
* #param args
* #throws LispEvaluatorException
*/
public static void main (String args[]) throws LispEvaluatorException
{
LispEvaluator expr= new LispEvaluator();
/**
* Expressions are tested.
* Note: For each operation written as (- 6), in order for the Stack to continue,
* it needs to be written as (- 0 6). This way, it is subtracting from a digit.
*/
String test1 = "(+ 5 0 10)";
String test2 = "(+ 5 0 10 (- 7 2))";
String test3 = "(+ (- 0 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))";
String test4 = "(+ (- 0 632) (* 21 3 4) (/ (+ 32) (* 1) (- 21 3 1)))";
String test5 = "(+ 2 6) (* 12 18) (/ (+ 32) (* 1) (- 21 3 1))";
String test6 = "(+ 1 2 (- 5 1) (*4 11 14))";
evaluateExprTest(test1, expr);
evaluateExprTest(test2, expr);
evaluateExprTest(test3, expr);
evaluateExprTest(test4, expr);
evaluateExprTest(test5, expr);
evaluateExprTest(test6, expr);
}
}
Custom exception class:
public class LispEvaluatorException extends Exception{
public LispEvaluatorException(String message) {
super(message);
}
}
The fixes are pretty straightforward: the crashes that you get are because unary operations are distinct features, so you need to code for them explicitly.
Fixing this problem consists of two parts:
Add a check for empty stack prior to the first pop()
Add a check for unary minus - and unary division /, which have separate code paths.
Here is the portion of the code that needs fixing:
switch (current_Operation) {
case "*":
if (currentOpStack.isEmpty()) {
result = 1;
break;
}
result = currentOpStack.pop();
while(!currentOpStack.isEmpty()){
result *= currentOpStack.pop();
}
break;
case "/":
if (currentOpStack.isEmpty()) {
result = 1;
break;
}
result = currentOpStack.pop();
if (currentOpStack.isEmpty()) {
// Unary division
result = 1.0 / result;
break;
}
while(!currentOpStack.isEmpty()){
result /= currentOpStack.pop();
}
break;
case "+":
if (currentOpStack.isEmpty()) {
result = 0;
break;
}
result = currentOpStack.pop();
while(!currentOpStack.isEmpty()){
result += currentOpStack.pop();
}
break;
case "-":
if (currentOpStack.isEmpty()) {
result = 0;
break;
}
result = currentOpStack.pop();
if (currentOpStack.isEmpty()) {
// Unary minus
result = -result;
break;
}
while(!currentOpStack.isEmpty()){
result -= currentOpStack.pop();
}
break;
default:
result = currentOpStack.pop();
break;
}
Demo.

Calculating expression by converting infix into postfix gives false output when number greater than 9

Here ch_st is my character stack and dbl_st is my double stack
class conversion_and_solution{
public static String postfix = "";//taken a string for the output
public boolean isOperand(char c){//checks weather it is operand or not
if(c>='0'&&c<='9')
return true;
return false;
}
public boolean isOperator(char c){//checks weather operator
if(c=='+'||c=='*'||c=='/'||c=='-')
return true;
return false;
}
public int Opweight(char op){//checks Operator weight
int op_wt = 0;
switch(op){
case '+':{
op_wt = 1;
break;
}
case '-':{
op_wt = 1;
break;
}
case '/':{
op_wt = 2;
break;
}
case '*':{
op_wt = 2;
break;
}
default:{
System.out.println("Not Operator");
break;
}
}
return op_wt;
}
public boolean HigherPrecedence(char op1,char op2){//checks the precedence
int p_op1 = Opweight(op1);
int p_op2 = Opweight(op2);
if(p_op1>p_op2)
return true;
return false;
}
public String convert_to_postfix(String expression){//this is for converting infix to postfix
char []chr = new char[expression.length()];
char_stack ch_st = new char_stack();//object of character stack
String ss = " ";
for(int i=0;i<expression.length();i++){
chr[i] = expression.charAt(i);
//Now simple condition for checking weather Operand , Operator etc and doing the job
if(isOperator(chr[i])){
while(!ch_st.isEmpty()&&ch_st.char_top()!='('&&HigherPrecedence(ch_st.char_top(),chr[i])){
postfix= postfix+ch_st.char_top();
ch_st.char_pop();
}
ch_st.char_push(chr[i]);
}
else if(isOperand(chr[i])){
postfix = postfix + chr[i];
}
else if(chr[i]=='('){
ch_st.char_push(chr[i]);
}
else if(chr[i]==')'){
while(!ch_st.isEmpty()&&ch_st.char_top()!='('){
postfix = postfix + ch_st.char_top();
ch_st.char_pop();
}
ch_st.char_pop();
}
}
while(!ch_st.isEmpty()){//till not empty will pop the value and make the stack empty giving the output
postfix = postfix + ch_st.char_top();
ch_st.char_pop();
}
return postfix;
}
public double solve_eqns(){
char []ch = new char[postfix.length()];
double_stack dbl_st = new double_stack();
double result;
for(int i=0;i<postfix.length();i++){
ch[i] = postfix.charAt(i);
if(isOperand(ch[i])){//Checks for Operand
double x = Character.getNumericValue(ch[i]);
dbl_st.dbl_push(x);
dbl_st.dbl_display();
}
//Now if tey are operators the task is performed
if(isOperator(ch[i])){
if(ch[i]=='/'){
double d1 = dbl_st.dbl_top();
dbl_st.dbl_pop();
double d2 = dbl_st.dbl_top();
dbl_st.dbl_pop();
double temp = d2/d1;
dbl_st.dbl_push(temp);
}
else if(ch[i]=='*'){
System.out.println("\n\nOperation to be done:*");
double d1 = dbl_st.dbl_top();
dbl_st.dbl_pop();
double d2 = dbl_st.dbl_top();
dbl_st.dbl_pop();
double temp = d2*d1;
dbl_st.dbl_push(temp);
}
else if(ch[i]=='+'){
System.out.println("\n\nOperation to be done:+");
double d1 = dbl_st.dbl_top();
dbl_st.dbl_pop();
double d2 = dbl_st.dbl_top();
dbl_st.dbl_pop();
double temp = d2+d1;
dbl_st.dbl_push(temp);
}
else if(ch[i]=='-'){
System.out.println("\n\nOperation to be done:-");
double d1 = dbl_st.dbl_top();
dbl_st.dbl_pop();
double d2 = dbl_st.dbl_top();
dbl_st.dbl_pop();
double temp = d2-d1;
dbl_st.dbl_push(temp);
}
}
}
result = dbl_st.dbl_top();
dbl_st.dbl_pop();
dbl_st.dbl_display();
System.out.println("\nOutput:"+result);
return result;
}
}
Here I am trying to solve an Infix Equation and I am getting false output as my code is considering every operator or operand as a character...
For example
If expression is (7+9)*4-12 gives correct output 52.
But if expression is (17+2)*4 then error occurs... it takes 7 and 1 as different numbers hence false output
So I want to know what changes in the code can make the inputs greater than 10 work properly
Here I am also not able to deal with unary operators
My advice is to revise your logic to take a more traditional approach of splitting lexical and semantic analysis. This will make your code more straightforward and easier to maintain than going directly from characters to interpretation.
However if you need to stick to your current approach then there is a relatively easy answer. In the code that processes operands you can continue to process numeric characters and add them as digits:
if (isOperand(ch[i])){
double x = Character.getNumericValue(ch[i]);
while (i < postFix.length() && isOperand(ch[i+1])) {
x = 10 * x + Character.getNumericValue(ch[++i]);
}
dbl_st.dbl_push(x);
dbl_st.dbl_display();
}
Though, as mentioned above, I would not recommend this approach. Much better is to convert to tokens before attempting to analyse semantics.

stack replaces all the entries in it with the last pushed element

I need some help on this one as I couldnt find a logical explanation for this anywhere. Maybe it is just a small mistake but I have been at the code for such a long time that I just cant see it. I have added comments where I am trying to push elements in my stack. I have two stacks one for all the operators and one for operands. The operator stack works fine but the operand stack is behaving weird. When I am trying to push elements it somehow replaces the stack elements with the latest element that I push. Whn I pop it returns the last element at all times. I have two different classes as operators and operands. Please let me know if you need the code for it. EDIT: The other classes dont do anything much though just a couple of getters, setters and checking for validity of tokens. Any help is appreciated. Thanks!
import java.util.*;
public class Evaluator {
private Stack<Operand> opdStack;
private Stack<Operator> oprStack;
public Evaluator() {
opdStack = new Stack<Operand>();
oprStack = new Stack<Operator>();
// HashMap<String, Operator> operators = new HashMap<String, Operator>();
Operator.operators.put("+",new AdditionOperator());
Operator.operators.put("-", new SubtractionOperator());
Operator.operators.put("*",new MultiplyOperator());
Operator.operators.put("/",new DivisionOperator());
Operator.operators.put("#",new BogusHash());
}
public int eval(String expr) {
String tok = "";
// init stack - necessary with operator priority schema;
// the priority of any operator in the operator stack other then
// the usual operators - "+-*/" - should be less than the priority
// of the usual operators
Operator newOpr = Operator.operators.get("#");
oprStack.push(newOpr);
String delimiters = "+-*/#! ";
StringTokenizer st = new StringTokenizer(expr,delimiters,true);
// the 3rd arg is true to indicate to use the delimiters as tokens, too
// but we'll filter out spaces
while (st.hasMoreTokens()) {
if ( !(tok = st.nextToken()).equals(" ")) { // filter out spaces
//System.out.println("equals");
if (Operand.check(tok)) { // check if tok is an operand
//System.out.println("tokens = "+tok);
//opdStack.push(new Operand ("0"));
opdStack.push(new Operand(tok));
System.out.println("stack peek "+ opdStack.peek().getValue());
//System.out.println(opdStack);
//System.out.println(oprStack);
} else {
//System.out.println("tokens = "+tok);
//System.out.println(newOpr);
if (!Operator.operators.containsKey(tok)) {
//System.out.println("tokens = "+tok);
//System.out.println(newOpr);
System.out.println("*****invalid token******"); System.exit(1);
}
Operator newOpr2 = Operator.operators.get(tok); // POINT 1
//System.out.println("Operator = "+oprStack.peek().priority());
while ( (oprStack.peek()).priority() >= newOpr2.priority()) {
//System.out.println("tokens while = "+tok);
System.out.println("tokens = "+tok);
Operator oldOpr = ((Operator)oprStack.pop());
//System.out.println("Opr"+oldOpr.priority());
Operand op2 = (Operand)opdStack.pop();
Operand op1 = (Operand)opdStack.pop();
System.out.println("run till here");
opdStack.push(oldOpr.execute(op1,op2));
System.out.println("Final res pushed opd= " + opdStack.peek().getValue());
}
oprStack.push(newOpr2);
//System.out.println("operand "+opdStack.toString());
}
}
}
//System.out.println("pop op2 = "+opdStack.pop().getValue()+" and pop op1 = "+opdStack.pop().getValue());
Operator newOp2 = ((Operator)oprStack.pop());
Operand op2 = (Operand)opdStack.get(0);
Operand op1 = (Operand)opdStack.get(1);
System.out.println("opd = "+ op1.getValue() + op2.getValue());
opdStack.push(newOp2.execute(op2, op1));
System.out.println("Full Stack opd size= "+ opdStack.size());
//System.out.println("Full Stack opd= "+ opdStack.toString());
Operand res = (Operand) opdStack.pop();
return res.getValue();
}
}
My Operand.java class
public class Operand {
static int val=0;
private static String strval="";
public Operand(String tok) {
// TODO Auto-generated constructor stub
strval = tok;
val = Integer.parseInt(strval);
// System.out.println("value = "+val);
}
public Operand(int value){
val = value;
//System.out.println("value = "+val);
}
public static boolean check(String tok) {
// TODO Auto-generated method stub
boolean bool;
try {
Integer.parseInt(tok);
bool = true;
} catch (Exception e){
//System.out.println("Type conversion "+e);
bool = false;
}
return bool;
}
public int getValue(){
//int re = Integer.parseInt(this.toString());
System.out.println("return value = " + val);
return val;
}
}

error in the given code for infix to postfix conversion for input containing more than 2 operands

static String convert(String exp)
{
String result="";
Stack s1=new Stack();
for(int i=0;i<exp.length();i++)
{
if(Character.isDigit(exp.charAt(i)))
{{
result=result+exp.charAt(i);
continue;
}
else
{
if(s1.empty())
{
s1.push(exp.charAt(i));
continue;
}
else
{
if(check(exp.charAt(i))>check(exp.charAt(i-1)))
s1.push(exp.charAt(i));
else
{
while(!s1.empty())
{
String a=s1.pop().toString();
result=result+a;
}
s1.push(exp.charAt(i));
}
}
}
}
while(!s1.empty())
{
String p=s1.pop().toString();
result=result+p;
}
return result;
}
static int check(char c)
{
switch (c) {
case '+':
case '-':
return 0;
case '*':
case '/':
return 1;
case '^':
return 2;
default:
throw new IllegalArgumentException("Operator unknown: " + c);
}
}
Here's my code to convert an expression from infix to postfix.
This code is working fine with just 2 operands..for more than 2 operands like 6+9*7 it shows
IllegalArgumentException which I have given in another method to set priorities of operators. Please help me to clarify where am I getting wrong?
Indent your code
In the stack trace:
at Test.convert(Test.java:21)
Is this line:
if(check(exp.charAt(i))>check(exp.charAt(i-1)))
So I think you mean:
if (check(exp.charAt(i)) > check(s1.peek()))
Now "The method check(char) in the type Test is not applicable for the arguments (Object)" is raised, so parameterized your Stack. That is, change:
Stack s1=new Stack();
To (in Java 7):
Stack<Character> s1 = new Stack<>();
You are getting this exception because of your logic. Consider 1+2*3. In this case, when you get 3 below code gets executed:
else
{
if(check(exp.charAt(i))>check(exp.charAt(i-1)))
s1.push(exp.charAt(i));
And check(3) results in
default:
throw new IllegalArgumentException("Operator unknown: " + c);

Stacks convertion from postfix to infix

Hello I am practicing some stacks on Java and I am trying to do a problem concerning stacks. I was trying to write a method that takes a postfix notation and converts it into infix. This is what i have so far:
`
public void convertion() {
Stack<Integer> stack; // For evaluating the expression.
stack = new Stack<Integer>(); // Make a new, empty stack.
Scanner scan = new Scanner(postfix);
int t1, t2 = 0; //Operands
boolean check = false;
while (scan.hasNext() && !check) {
if (scan.hasNextInt()) {
int operand = scan.nextInt();
stack.push(operand);
} else {
char operator = scan.next().charAt(0);
try {
while(stack.)
} catch (EmptyStackException e) {
answer = "Malformed postfix expression";
check = true;
}
}
}
scan.close();
try {
answer = "" + stack.pop();
} catch (EmptyStackException e) {
answer = "Malformed postfix expression";
}
}
`
The part im having trouble with is on what i should put on the try part. Basically Im pushing all the numbers i find into the stack, but once i find an operator, how do i merge the two operands and the operator.
Thanks.
You want to pop the top two stack elements, perform the appropriate operation on them and then push back the result:
try {
int o1 = stack.pop().intValue();
int o2 = stack.pop().intValue();
switch (operator) {
case '+': stack.push(new Integer(o1 + o2));
break;
case '-': stack.push(new Integer(o1 - o2));
break;
...
}
}
catch (EmptyStackException e) {
...

Categories