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条)

报告相同问题?

悬赏问题

  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化
  • ¥15 Mirare PLUS 进行密钥认证?(详解)
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥20 想用ollama做一个自己的AI数据库
  • ¥15 关于qualoth编辑及缝合服装领子的问题解决方案探寻
  • ¥15 请问怎么才能复现这样的图呀