由於工作需要,寫了一個使用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; }
