In my program I am working on converting from infix to postfix. I have a method named isOperator(), which will return true if the precedance of the operator is greater than 0.
I am supposed to rewrite the toPostfix() method using isOperator(), but I am unsure where to begin.
public class Expression {
private static final String SPACE = " ";
private static final String PLUS = "+";
private static final String MINUS = "-";
public static int rank(String operator) {
switch (operator) {
case "*":
case "/":
return 2;
case PLUS:
case MINUS: //2
return 1;
default:
return -1;
}
}
public static boolean isOperator(String token) { //4
if (rank(token) > 0){
return true;
}
return false;
}
public static String toPostfix(String infixExpr) {
StringBuilder output = new StringBuilder();
Stack<String> operators = new ArrayStack<>();
for (String token: infixExpr.split("\\s+")) {
if (rank(token) > 0) { // operator
// pop equal or higher precedence
while (!operators.isEmpty() &&
rank(operators.peek()) >= rank(token)) {
output.append(operators.pop() + SPACE);
}
operators.push(token);
} else { // operand
output.append(token + SPACE);
}
}
while (!operators.isEmpty()) {
output.append(operators.pop() + SPACE);
}
return output.toString();
}
public static void main(String[] args) {
System.out.println(rank("/"));
String infix = "a * b * c + d / e / f";
System.out.println(toPostfix(infix));
}
}
Change if(rank(token) > 0){ in your postfix method to isOperator(token)
Change: if(rank(token) > 0){
To: isOperator(token)
Related
I wrote a code that reads any arithmetic expression in form of a string and returns the result by printing it.
All of this is done with regard to the order of operation (PEMDAS).
As an example the input, "2+7*5+3" should return 40
But the problem is that the program doesn't return the correct result and I don't know what seems to be the problem.
The Code:
public class LL {
public static int calc(String op, int n1,int n2){
if(op.equals("+")){
return n1+n2;
}
else if(op.equals("-")){
return n1-n2;
}
else if(op.equals("/")){
return n1/n2;
}
else{
return n1*n2;
}
}
public static boolean check(String oldop, String newop){
if(oldop==null||oldop.equals("=")){
return true;
}
else if(oldop.equals("+")||oldop.equals("-")){
if(newop.equals("+")||newop.equals("-")||newop.equals("/")||newop.equals("*")){
return true;
}
else{
return false;
}
}
else{
if(newop.equals("/")||newop.equals("*")){
return true;
}
else{
return false;
}
}
}
public static void main(String[] args) {
int ch=0;
LinkedList<String> op = new LinkedList<String>();
LinkedList<String> nums = new LinkedList<String>();
Scanner sc = new Scanner(System.in);
String exp = sc.nextLine();
String[] exparr = exp.split(" ");
for(int i = 0 ; i<exparr.length-1;i+=2){
nums.push(exparr[i]);
String oldop = op.pop();
if(check(oldop,exparr[i+1])){
if(oldop!=null)
op.push(oldop);
op.push(exparr[i+1]);
}
else{
String n2=nums.pop();
String n1=nums.pop();
int nn2=Integer.parseInt(n2);
int nn1=Integer.parseInt(n1);
int res = calc(oldop,nn1,nn2);
nums.push(Integer.toString(res));
op.push(exparr[i+1]);
}
}
nums.push(exparr[exparr.length-1]);
String opp = op.pop();
while(opp!=null){
String n2=nums.pop();
String n1=nums.pop();
int nn2=Integer.parseInt(n2);
int nn1=Integer.parseInt(n1);
int res = calc(opp,nn1,nn2);
nums.push(Integer.toString(res));
opp = op.pop();
}
System.out.println(nums.pop());
}
}
Your check method is wrong. You must return true if the old operation is + or - and the new operation is * or / otherwise return false.
public static boolean check(String oldop, String newop){
if(oldop == null || oldop.equals("=")){
return true;
}
return (oldop.equals("+") || oldop.equals("-")) && (newop.equals("/") || newop.equals("*"));
}
Another point is, don't use pop method of LinkedList, this method throws an exception if the list is empty, use poll method that return null if the list is empty.
The other code is correct.
I'm trying to implement this pseudo-code in java, to evaluate an arithmetic expression. But I keep getting the last digit: ie if i do 1+2, i'd just get 2; I don't know what I'm doing incorrectly, so If anyone has any idea, please let me know!!
Algorithm here
import java.util.Stack;
public class Main {
static Stack<String> ops = new Stack<String>();
static Stack<Double> vals = new Stack<Double>();
private static void doOP() {
double x = vals.pop();
double y = vals.pop();
String op = ops.pop();
double v = 0;
if (op.equals("+")) {
v = y + x;
} else {
if (op.equals("-")) {
v = y - x;
} else {
if (op.equals("*")) {
v = y * x;
} else {
if (op.equals("/")) {
v = y / x;
}
}
}
}
vals.push(v);
}
private static void repeatOps(String refOp) {
while ((vals.size() > 1) && (prec(refOp) <= prec(ops.peek()))) {
doOP();
}
}
private static int prec(String refOp) {
String[] bodmas = new String[] { "(", ")", "/", "*", "+", "-", "$" };
int i = 0;
for (String operation : bodmas) {
if (refOp.equals(operation)) {
return i;
}
i++;
}
return -0;
}
private static boolean isNumber(String number) {
try {
#SuppressWarnings("unused")
double d = Double.parseDouble(number);
} catch (Exception e) {
return false;
}
return true;
}
private static Double evalExp(String exp) {
for (char z : exp.toCharArray()) {
if (isNumber(z + "")) {
vals.push(Double.parseDouble(z + ""));
} else {
repeatOps(z + "");
ops.push(z + "");
}
}
repeatOps("$");
return vals.peek();
}
public static void main(String[] args) {
System.out.println(evalExp("3*2"));
}
}
Your prec() method is inverted and incorrect.
$ should be lowest precedence, meaning lowest value, e.g. 0.
+ and - should have same precedence.
* and / should have same precedence.
( and ) are not binary operators, and cannot be handled with the described logic.
So, fix prec to return 0 for $, 1 for + and -, and 2 for * and /.
I found the code of Math Expression Parser from Dreamincode Forum.
My question is, on that code I think everything is going all right, but when I had a testcase '(2(3+5)' , that was valid, whereas this test case is completely wrong
but if I give the test case '(3+5)2)' it was detect as non valid input.
Anyone knows why this is happening?
//enum for Operator "objects"
import java.util.*;
public enum Operator {
ADD("+", 1)
{
double doCalc(double d1, double d2) {
return d1+d2;
}
},
SUBTRACT("-",1)
{
double doCalc(double d1, double d2) {
return d1-d2;
}
},
MULTIPLY("*", 2)
{
double doCalc(double d1, double d2) {
return d1*d2;
}
},
DIVIDE("/",2)
{
double doCalc(double d1, double d2) {
return d1/d2;
}
},
STARTBRACE("(", 0)
{
double doCalc(double d1, double d2) {
return 0;
}
},
ENDBRACE(")",0)
{
double doCalc(double d1, double d2) {
return 0;
}
},
EXP("^", 3)
{
double doCalc(double d1, double d2) {
return Math.pow(d1,d2);
}
};
private String operator;
private int precedence;
private Operator(String operator, int precedence) {
this.operator = operator;
this.precedence = precedence;
}
public int getPrecedenceLevel() {
return precedence;
}
public String getSymbol() {
return operator;
}
public static boolean isOperator(String s) {
for(Operator op : Operator.values()) { //iterate through enum values
if (op.getSymbol().equals(s))
return true;
}
return false;
}
public static Operator getOperator(String s)
throws InvalidOperatorException {
for(Operator op : Operator.values()) { //iterate through enum values
if (op.getSymbol().equals(s))
return op;
}
throw new InvalidOperatorException(s + " Is not a valid operator!");
}
public boolean isStartBrace() {
return (operator.equals("("));
}
//overriding calculation provided by each enum part
abstract double doCalc(double d1, double d2);
}
//error to be thrown/caught in ProjectOne.java
class InvalidOperatorException extends Exception {
public InvalidOperatorException() {
}
public InvalidOperatorException(String s) {
super(s);
}
}
//reading in a string at doing the parsing/arithmetic
public static void main (String[] args) {
String input = "";
//get input
System.out.print("Enter an infix exp<b></b>ression: ");
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
try {
input = in.readLine();
}
catch (IOException e)
{
System.out.println("Error getting input!");
}
doCalculate(input);
}
// Input: user entered string
// Output: Display of answer
public static void doCalculate(String equation) {
//our stacks for storage/temp variables
Stack<Operator> operatorStack;
Stack<Double> operandStack;
double valOne, valTwo, newVal;
Operator temp;
//initalize
StringTokenizer tokenizer = new StringTokenizer(equation, " +-*/()^", true);
String token = "";
operandStack = new Stack();
operatorStack = new Stack();
try {
while(tokenizer.hasMoreTokens()){ //run through the string
token = tokenizer.nextToken();
if (token.equals(" ")) { //handles spaces, goes back up top
continue;
}
else if (!Operator.isOperator(token)){ //number check
operandStack.push(Double.parseDouble(token));
}
else if (token.equals("(")) {
operatorStack.push(Operator.getOperator(token));
}
else if (token.equals(")")) { //process until matching paraentheses is found
while (!((temp = operatorStack.pop()).isStartBrace())) {
valTwo = operandStack.pop();
valOne = operandStack.pop();
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
}
else { //other operators
while (true) { //infinite loop, check for stack empty/top of stack '('/op precedence
if ((operatorStack.empty()) || (operatorStack.peek().isStartBrace()) ||
(operatorStack.peek().getPrecedenceLevel() < Operator.getOperator(token).getPrecedenceLevel())) {
operatorStack.push(Operator.getOperator(token));
break; //exit inner loop
}
temp = operatorStack.pop();
valTwo = operandStack.pop();
valOne = operandStack.pop();
//calculate and push
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
}
}
}
catch (InvalidOperatorException e) {
System.out.println("Invalid operator found!");
}
//calculate any remaining items (ex. equations with no outer paraentheses)
while(!operatorStack.isEmpty()) {
temp = operatorStack.pop();
valTwo = operandStack.pop();
valOne = operandStack.pop();
newVal = temp.doCalc(valOne, valTwo);
operandStack.push(newVal);
}
//print final answer
System.out.println("Answer is: " + operandStack.pop());
}
This calculator does not work with implicit multiplication. you can use:
2((2+2)+1)
And see that it gives the wrong answer as opposed to:
2*((2+2)+1)
The false-positive expression you've used does not pass with explicit multiplication.
A quick for-the-lazy fix to add implicit multiplication would be something of that sort:
public static void doCalculate(String equation) {
// make it explicit:
System.out.println("Got:" + equation);
Pattern pattern = Pattern.compile("([0-9]+|[a-z\\)])(?=[0-9]+|[a-z\\(])");
Matcher m = pattern.matcher(equation);
System.out.println("Made it: "+ (equation = m.replaceAll("$1*")));
//our stacks for storage/temp variables
Stack<Operator> operatorStack;
Stack<Double> operandStack;
double valOne, valTwo, newVal;
Operator temp;
This is an attempt to capture implicit multiplication using regex and make it explicit.
It fixes all cases we've come up with.
I've tried writing this code from scratch, coding, and running it but it just doesn't seem to work. This was assigned as lab work in class. The requirements are:
Implementing a postfix evaluation with the use of a stack and stack operations (user-defined).
I think the algorithm of my program is right, but it always gives me the wrong answer.
Here is my code.
public class StackApplication {
public static class Stack<T> {
private int top = 0;
private final static int stackMax=100;
// highest index of stk array
private Object[] stk = new Object[stackMax+1];
//Elements must be cast back.
public Stack() { // constructor
}
public boolean isEmpty(){
if (top==0) return true;
else return false;
}
public void push(T el) {
if(top==stackMax)
System.out.println("Stack push overflow error");
else top=top+1;
stk[top]=el;
}
public T pop(){
if(isEmpty()){
System.out.println("Stack push underflow error");
return null;
}
else top=top-1;
return(T)stk[top+1];
}
public T top(){
if(isEmpty()){
//System.out.println("Stack empty");
return null;
}
else return (T)stk[top];
}
}
public static boolean isOperator(char c){
return(c=='+' || c=='-' || c=='/' || c=='*' || c=='^');
}
public static double evaluate(double x, char o, double y) {
double result=0;
switch(o) {
case '+' : result=x+y; break;
case '-' : result=x-y; break;
case '*' : result=x*y; break;
case '/' : result=x/y; break;
case '^' : result=Math.pow(x, y); break;
default : break;
}
return result;
}
public static void main(String[] args) {
Scanner console=new Scanner(System.in);
Stack<Double> s=new Stack<Double>();
System.out.println("Input Postfix form to evaluate:");
String inp=console.nextLine();
char[] chararray=inp.toCharArray();
double b,a;
for(int i=0; i<chararray.length; i++) {
if(!isOperator(chararray[i]))
s.push((double)chararray[i]);
else {
b=s.pop();
a=s.pop();
double c=evaluate(a, chararray[i], b);
s.push(c);
}
}
System.out.println(" " +s.pop());
}
}
Sample Output:
Input Postfix form to evaluate:
23+ (Input)
101.0 (Output)
5.0 (Expected output)
The problem is here: s.push((double)chararray[i]);. You can't convert char to double this way. You are now taking the ascii code of 2 and 3.
50(ascii code of 2) + 51(ascii code of 3) = 101
Do it like this: s.push((double)(chararray[i] - '0'));
Your are doing the addition of the ASCII codes for 2 and 3, not of 2 and 3.
The code for 2 is 50 and for 3 is 51, so your out is 101, which is correct in this case.
When you push, push chararray[i]-'0'. This will solve your problem.
I have 2 integers:
int first= 10;
int second = 20;
and a string representing the operation (one of +, -, /, or *):
String op = "+";
How can I get the result of 10 + 20 in this example?
I don't recommend this but is funny. in java6
String op = '+';
int first= 10;
int second = 20;
ScriptEngineManager scm = new ScriptEngineManager();
ScriptEngine jsEngine = scm.getEngineByName("JavaScript");
Integer result = (Integer) jsEngine.eval(first+op+second);
go with the switch, but remember to convert the string operator to char as switch don't works with strings yet.
switch(op.charAt(0)){
case '+':
return first + second;
break;
// and so on..
switch (op.charAt(0)) {
case '+': return first + second;
case '-': return first - second;
// ...
}
you can try the following code. It's object oriented, quite generic, and you can easily extend it to add new operators, including operators with a different number of arguments:
public abstract class Operator {
public abstract Integer compute(Integer...values);
}
public class Plus extends Operator {
public Integer compute(Integer...values) {
return values[0] + values[1];
}
}
public class Minus extends Operator {
public Integer compute(Integer...values) {
return values[0] - values[1];
}
}
public class Multiply extends Operator {
public Integer compute(Integer...values) {
return values[0] * values[1];
}
}
public class Divide extends Operator {
public Integer compute(Integer...values) {
return values[0] / values[1];
}
}
Map operatorMap = createOperatorMap();
public Map createOperatorMap() {
Map<String, Operator> map = new HashMap<String, Operator>();
map.put("+", new Plus());
map.put("-", new Minus());
map.put("*", new Multiply());
map.put("/", new Divide());
return map;
}
public int compute(int a, int b, String opString) {
Operator op = operatorMap.get(opString);
if (op == null)
throw new IllegalArgumentException("Unknown operator");
return op.compute(a, b);
}
public double doMath(int first, int second, char op ){
switch(op){
case '+':
return first + second;
break;
case '-':
return first - second;
break;
case '*':
return first * second;
break;
case '/':
return first / second;
break;
default:
return 0;
}
}
switch(string){
}
(switch on strings)will be allowed in Java7. Now you can switch with char
switch(string.charAt(0)){
case '+' : ...
}
as mentioned above