JAVA实现简易计算器

和自甴很熟 提交于 2020-02-29 15:41:02

简易计算器,可实现任意长度带括号带优先级的 ‘加减乘除幂’ 运算
还未加入报错机制,需要求表达式书写正确,不能存在左右括号数目不等或右括号前没有数字或除数为0等情况

/*
    科学计算器,可实现任意长度带括号带优先级的 '加减乘除幂' 运算
    还未加入报错机制,需要求表达式书写正确,不能存在左右括号数目不等或右括号前没有数字或除数为0等情况
 */
import java.util.Hashtable;
import java.util.Stack;

public class ScientificCalculator {

    public static double calc(double a, double b, char operator){
        switch (operator){
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                return a / b;
            case '^':
                return Math.pow(a,b);
        }
        return 0.0d;
    }
    //出栈两个操作数,一个操作符,运算结果入操作数    需重复运算,所以写成一个函数
    public static void calcTwo(Stack<Double> stack1, Stack<Character> stack2){
        double a = 0.0d;
        double b = 0.0d;
        double c = 0.0d;
        char ope = ' ';
        b = stack1.pop();           //出栈两个操作数一个操作符,运算结果入栈
        a = stack1.pop();
        ope = stack2.pop();
        c = calc(a,b,ope);
        stack1.push(c);
    }
    /*规则:
     *依次处理每个字符
     *1.是数字则暂存起来
     *2.是左括号压入堆栈
     *3.是右括号则运算至操作符栈顶为左括号
     *4.是运算符:
     *    将暂存的字符压入数字栈
     *    若优先级大于栈顶运算符 或 运算符栈为空 或 栈顶运算符为左括号,压入栈
     *    若优先级小于或等于栈顶运算符,弹出两个数进行计算
     *5.对象处理完毕后,计算栈中元素直至栈空
     */
    public static double scientificCalculate(String str){
        Stack<Double> num_stack = new Stack<>(); //操作数栈
        Stack<Character> sym_stack = new Stack<>(); //操作符栈
        int num_brackets = 0; //括号层数
        Hashtable<Character,Integer> pri_map = new Hashtable<>();//操作符优先级
        pri_map.put('+', 0);
        pri_map.put('-', 0);
        pri_map.put('*', 1);
        pri_map.put('/', 1);
        pri_map.put('^', 2);
        pri_map.put('(', 0);
        pri_map.put(')', 0);
        double result = 0.0d;
        String res = "";
        double res_trans = 0.0d; //字符串转double类型

        for(int i = 0 ;i < str.length();i++){
            if((str.charAt(i) != '+') && (str.charAt(i) != '-') && (str.charAt(i) != '*') && (str.charAt(i) != '/' && (str.charAt(i) != '^') && (str.charAt(i) != '(') && (str.charAt(i) != ')'))){
                res += str.charAt(i);
            }
            //当前元素为运算符
            else if((str.charAt(i) == '+') || (str.charAt(i) == '-') || (str.charAt(i) == '*') || (str.charAt(i) == '/') || (str.charAt(i) == '^')){
                if(str.charAt(i-1) != ')') {
                    res_trans = Double.valueOf(res); //操作数入栈
                    num_stack.push(res_trans);
                    res = "";
                }
                //操作符栈为空 或 当前运算符优先级大于栈顶运算符优先级 或 操作符栈顶元素为左括号 ,则操作符入栈
                if((sym_stack.empty()) || (pri_map.get(str.charAt(i))>pri_map.get(sym_stack.peek())) || (sym_stack.peek() == '(')){
                    sym_stack.push(str.charAt(i));
                }else{
                    calcTwo(num_stack,sym_stack);
                    sym_stack.push(str.charAt(i));
                }
            }
            //如果是左括号则入操作符栈
            else if(str.charAt(i) == '('){
                sym_stack.push(str.charAt(i));
                num_brackets ++;
            }
            //如果是右括号则运算至操作符栈顶为左括号
            else if(str.charAt(i) == ')'){
                if(str.charAt(i-1) != ')') {
                    res_trans = Double.valueOf(res); //操作数入栈
                    num_stack.push(res_trans);
                    res = "";
                }

                if(sym_stack.peek() == '('){
                    sym_stack.pop();
                    num_brackets--;
                }else{
                    do{
                        calcTwo(num_stack,sym_stack);
                    }while(sym_stack.peek() != '(');
                    sym_stack.pop();
                    num_brackets--;
                }
            }
        }
        if(res != "") {
            res_trans = Double.valueOf(res); //操作数入栈
            num_stack.push(res_trans);
        }
        calcTwo(num_stack,sym_stack);
        //一直运算至操作符栈为空
        while(!sym_stack.empty()){
            calcTwo(num_stack,sym_stack);
        }
        result = num_stack.peek();
        return result;
    }
    public static void main(String[] args) {
        System.out.println("科学计算器,可实现任意长度带括号带优先级的‘+-*/幂'运算");
        double result1 = scientificCalculate("(5.2*6*3+(5+5)*2)*3");
        System.out.println(result1);
        double result2 = scientificCalculate("3*(5+6*3+5*5^2)");
        System.out.println(result2);
        double result3 = scientificCalculate("(1+2)*(5+6*(1+2)+5*5^2)");
        System.out.println(result3);
    }
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!