数学表达式解析器 [英] Math Expression Parser

查看:99
本文介绍了数学表达式解析器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Dreamincode论坛上找到了Math Expression Parser的代码.

I found the code of Math Expression Parser from Dreamincode Forum.

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

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

但是如果我给出测试用例'(3 + 5)2)',则被检测为无效输入. 有人知道为什么会这样吗?

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.

这篇关于数学表达式解析器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆