Seemyeyes7 2019-10-14 15:45 采纳率: 50%
浏览 664
已采纳

JAVA实现算术表达式的求值

补充中间有补充代码提示的地方就好能附上说明更好

package eval;

public class Util {

    /**
     * 计算表达式 express 的值
     * 如: eval("3+5*3") 返回 18
     */
    public static double eval(String express) {
        char[] chars = express.toCharArray();

        // .... 补充代码 ....

        return 0;
    }

    /**
     * 求 a 和 b 进行算术运算的结果。 
     * 例如:calculate(3, 5, '+') 返回  8
     */
    private static double calculate(double a, double b, char op) {
        switch (op) {
        case '+':
            return a + b; 
        case '-':
            return a - b; 
        case '*':
            return a * b; 
        case '/':
            return a / b; 
        default:
            throw new RuntimeException("不支持此运算"); 
        }
    }
}

  • 写回答

4条回答 默认 最新

  • 关注
    import java.util.Collections;
    import java.util.Stack;
    
    public class Calculator {
        private Stack<String> postfixStack  = new Stack<String>();//后缀式栈
        private Stack<Character> opStack  = new Stack<Character>();//运算符栈
        private int [] operatPriority  = new int[] {0,3,2,1,-1,1,0,2};//运用运算符ASCII码-40做索引的运算符优先级
        public static void main(String[] args) {
            System.out.println(5+12*(3+5)/7.0);
            Calculator cal  = new Calculator();
            String s = "5+12*(3+5)/7";
            double result  = cal.calculate(s);
            System.out.println(result);
        }
    
        /**
         * 按照给定的表达式计算
         * @param expression 要计算的表达式例如:5+12*(3+5)/7
         * @return
         */
        public double calculate(String expression) {
            Stack<String> resultStack  = new Stack<String>();
            prepare(expression);
            Collections.reverse(postfixStack);//将后缀式栈反转
            String firstValue  ,secondValue,currentValue;//参与计算的第一个值,第二个值和算术运算符
            while(!postfixStack.isEmpty()) {
                currentValue  = postfixStack.pop();
                if(!isOperator(currentValue.charAt(0))) {//如果不是运算符则存入操作数栈中
                    resultStack.push(currentValue);
                } else {//如果是运算符则从操作数栈中取两个值和该数值一起参与运算
                     secondValue  = resultStack.pop();
                     firstValue  = resultStack.pop();
                     String tempResult  = calculate(firstValue, secondValue, currentValue.charAt(0));
                     resultStack.push(tempResult);
                }
            }
            return Double.valueOf(resultStack.pop());
        }
    
        /**
         * 数据准备阶段将表达式转换成为后缀式栈
         * @param expression
         */
        private void prepare(String expression) {
            opStack.push(',');//运算符放入栈底元素逗号,此符号优先级最低
            char[] arr  = expression.toCharArray();
            int currentIndex  = 0;//当前字符的位置
            int count = 0;//上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值
            char currentOp  ,peekOp;//当前操作符和栈顶操作符
            for(int i=0;i<arr.length;i++) {
                currentOp = arr[i];
                if(isOperator(currentOp)) {//如果当前字符是运算符
                    if(count > 0) {
                        postfixStack.push(new String(arr,currentIndex,count));//取两个运算符之间的数字
                    }
                    peekOp = opStack.peek();
                    if(currentOp == ')') {//遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号
                        while(opStack.peek() != '(') {
                            postfixStack.push(String.valueOf(opStack.pop()));
                        }
                        opStack.pop();
                    } else {
                        while(currentOp != '(' && peekOp != ',' && compare(currentOp,peekOp) ) {
                            postfixStack.push(String.valueOf(opStack.pop()));
                            peekOp = opStack.peek();
                        }
                        opStack.push(currentOp);
                    }
                    count = 0;
                    currentIndex = i+1;
                } else {
                    count++;
                }
            }
            if(count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {//最后一个字符不是括号或者其他运算符的则加入后缀式栈中
                postfixStack.push(new String(arr,currentIndex,count));
            } 
    
            while(opStack.peek() != ',') {
                postfixStack.push(String.valueOf( opStack.pop()));//将操作符栈中的剩余的元素添加到后缀式栈中
            }
        }
    
        /**
         * 判断是否为算术符号
         * @param c
         * @return
         */
        private boolean isOperator(char c) {
            return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' ||c == ')';
        }
    
        /**
         * 利用ASCII码-40做下标去算术符号优先级
         * @param cur
         * @param peek
         * @return
         */
        public  boolean compare(char cur,char peek) {// 如果是peek优先级高于cur,返回true,默认都是peek优先级要低
            boolean result  = false;
            if(operatPriority[(peek)-40] >= operatPriority[(cur) - 40]) {
               result = true;
            }
            return result;
        }
    
        /**
         * 按照给定的算术运算符做计算
         * @param firstValue
         * @param secondValue
         * @param currentOp
         * @return
         */
        private String calculate(String firstValue,String secondValue,char currentOp) {
            String result  = "";
            switch(currentOp) {
                case '+':
                    result = String.valueOf(ArithHelper.add(firstValue, secondValue));
                    break;
                case '-':
                    result = String.valueOf(ArithHelper.sub(firstValue, secondValue));
                    break;
                case '*':
                    result = String.valueOf(ArithHelper.mul(firstValue, secondValue));
                    break;
                case '/':
                    result = String.valueOf(ArithHelper.div(firstValue, secondValue));
                    break;
            }
            return result;
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!