qq_36625984 2017-04-28 01:36 采纳率: 100%
浏览 2898
已采纳

Java计算器多个数一起运算问题

网上找的代码都是只能一次实现两个数之间的四则运算(也就是跟window自带计算器一样),那怎么实现多个数之间的运算呢?
如输入1+3*2=
输出:7
也就是用户可以输入一大串数字,自动满足运算法则出结果(满足运算法则)。
简单说明做法即可。感谢。

  • 写回答

3条回答 默认 最新

  • threenewbee 2017-04-28 02:07
    关注
     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;
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 VFP如何使用阿里TTS实现文字转语音?
  • ¥100 需要跳转番茄畅听app的adb命令
  • ¥50 寻找一位有逆向游戏盾sdk 应用程序经验的技术
  • ¥15 请问有用MZmine处理 “Waters SYNAPT G2-Si QTOF质谱仪在MSE模式下采集的非靶向数据” 的分析教程吗
  • ¥50 opencv4nodejs 如何安装
  • ¥15 adb push异常 adb: error: 1409-byte write failed: Invalid argument
  • ¥15 nginx反向代理获取ip,java获取真实ip
  • ¥15 eda:门禁系统设计
  • ¥50 如何使用js去调用vscode-js-debugger的方法去调试网页
  • ¥15 376.1电表主站通信协议下发指令全被否认问题