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;
    }

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM