zoukankan      html  css  js  c++  java
  • 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;
        }
     
  • 相关阅读:
    [CoreOS 转载]CoreOS实践指南(二):架设CoreOS集群
    [CoreOS 转载] CoreOS实践指南(一)
    [CoreOS]CoreOS 实战:CoreOS 及管理工具介绍
    [SQL in Azure] Configure a VNet to VNet Connection
    [SQL in Azure] Tutorial: AlwaysOn Availability Groups in Azure (GUI)
    [SQL in Azure] High Availability and Disaster Recovery for SQL Server in Azure Virtual Machines
    [SQL in Azure] Windows Azure Virtual Machine Readiness and Capacity Assessment
    [SQL in Azure] Provisioning a SQL Server Virtual Machine on Azure
    [SQL in Azure] Getting Started with SQL Server in Azure Virtual Machines
    [SQL Server 2014] 微软将于年底发布新版数据库SQL Server 2014
  • 原文地址:https://www.cnblogs.com/blog5277/p/5707304.html
Copyright © 2011-2022 走看看