简体   繁体   English

数学表达式解析器

[英]Math Expression Parser

I found the code of Math Expression Parser from Dreamincode Forum. 我从Dreamincode论坛找到了Math Expression Parser的代码。

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 我的问题是,在该代码上,我认为一切都很好,但是当我有一个测试用例'(2(3 + 5)'时,那是有效的,而此测试用例是完全错误的

but if I give the test case '(3+5)2)' it was detect as non valid input. 但是如果我给出测试用例'(3 + 5)2)',则被检测为无效输入。 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. 它可以解决我们提出的所有情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM