Java使用BigDecimal精确计算的简单公式计算器

由于工作需要,写了一个使用BigDecimal运算的精确计算的计算器(然后发现其实比不用BigDecimal的并好不到哪里去)

只能做加减乘除

double类型的数字在千万级别的时候会转成科学计数法,我这个不会(我估计能有方法不以科学计数法显示)

其中用到的知识就是中缀表达式转后缀表达式,我是从这里学的:

http://www.cnblogs.com/mygmh/archive/2012/10/06/2713362.html

下面上代码吧:

这个方法需要一个参数,String类型公式,形如:"1+(2-3*4)/5";
这个方法用来对已经转换成后缀表达式的公式进行处理

public static BigDecimal getResult(String input){
        //规范输入形式,避免用户输入中文括号
        input=input.replaceAll("(","(");
        input=input.replaceAll(")",")");
        //对输入公式,按符号/数字,用空格分开,以便后面分组
        String[] inputs=input.split("");
        String format="";
        for (int i=0;i<inputs.length;i++){
            if (inputs[i].equals(" ")){
                continue;
            }else if (inputs[i].equals("(")||inputs[i].equals(")")||inputs[i].equals("+")||inputs[i].equals("-")||inputs[i].equals("*")||inputs[i].equals("/")){
                format+=" "+inputs[i]+" ";
            }else {
                format+=inputs[i];
            }
        }
        List<String> strings=changeInfixExpressionToPostfixExpression(format);
        Stack<String> stack=new Stack<String>();
        for (int i=0;i<strings.size();i++){
            if (strings.get(i).equals("+")){
                BigDecimal a=new BigDecimal(stack.pop());
                BigDecimal b=new BigDecimal(stack.pop());
                stack.add(b.add(a).toString());
            }else if (strings.get(i).equals("-")){
                BigDecimal a=new BigDecimal(stack.pop());
                BigDecimal b=new BigDecimal(stack.pop());
                stack.add(b.subtract(a).toString());
            }else if (strings.get(i).equals("*")){
                BigDecimal a=new BigDecimal(stack.pop());
                BigDecimal b=new BigDecimal(stack.pop());
                stack.add(b.multiply(a).toString());
            }else if (strings.get(i).equals("/")){
                BigDecimal a=new BigDecimal(stack.pop());
                BigDecimal b=new BigDecimal(stack.pop());
                //这里的1000是做除法以后计算的精确位数,就算1000位也并不会拖慢程序速度,一个公式0.01秒内就能算完,后面的是除不尽的四舍五入
                stack.add(b.divide(a,1000,BigDecimal.ROUND_HALF_DOWN).toString());
            }else {
                stack.add(strings.get(i));
            }
        }
        //返回的时候格式化一下,取四舍五入小数点后两位
        return new BigDecimal(stack.pop()).setScale(2,BigDecimal.ROUND_HALF_DOWN);
    }

 

这个方法呢,就是将输入的中缀表达式转成后缀表达式:

public static List changeInfixExpressionToPostfixExpression(String input){
        List<String> resultList=new ArrayList<String>();
        Stack<String> tempStack=new Stack<String>();
        String[] splitArray=input.split(" ");
        for (int i=0;i<splitArray.length;i++){
            if (splitArray[i].equals("")){
                continue;
            }
            //如果字符是右括号的话,说明前面一定有过左括号,将栈里第一个左括号之前全部添加到List里
            if (splitArray[i].equals(")")){
                while (!tempStack.peek().equals("(")){
                    resultList.add(tempStack.pop());
                }
                tempStack.pop();//去除前面的左括号
            }else if (splitArray[i].equals("(")){
                //如果是左括号,那么直接添加进去
                tempStack.add("(");
            }else if (splitArray[i].equals("+")||splitArray[i].equals("-")){
                //如果是加减号,还需要再判断
                if (tempStack.empty()||tempStack.peek().equals("(")){
                    tempStack.add(splitArray[i]);
                }else if (tempStack.peek().equals("+")||tempStack.peek().equals("-")){
                    //读临时栈里的顶部数据,如果也是加减就取出来一个到结果列,这个放临时栈,如果是乘除就开始取到右括号为止
                    resultList.add(tempStack.pop());
                    tempStack.add(splitArray[i]);
                }else {
                    while (!tempStack.empty()){
                        if (tempStack.peek().equals("(")){
                            break;
                        }else {
                            resultList.add(tempStack.pop());
                        }
                    }
                    tempStack.add(splitArray[i]);
                }
            }else if (splitArray[i].equals("*")||splitArray[i].equals("/")){
                //如果是乘除
                if (!tempStack.empty()){
                    //判断临时栈里栈顶是啥,如果是乘除,取一个出来到结果列,添这个进临时栈
                    if (tempStack.peek().equals("*")||tempStack.peek().equals("/")){
                        resultList.add(tempStack.pop());
                    }
                }
                tempStack.add(splitArray[i]);
            }else {
                //说明是非符号,都添加进去
                resultList.add(splitArray[i]);
            }
        }
        //遍历完了,把临时stack里的东西都加到结果stack里去
        while (!tempStack.empty()){
            resultList.add(tempStack.pop());
        }
        return resultList;
    }

 

 

 
posted @ 2016-07-26 14:19  曲高终和寡  阅读(3299)  评论(0编辑  收藏  举报