Java字符串轉換成算術表達式計算並輸出結果,通過這個工具可以直接對字符串形式的算術表達式進行運算,並且使用非常簡單。
這個工具中包含兩個類Calculator 和ArithHelper
Calculator 代碼如下:
import java.util.Collections;import java.util.Stack;/** * 算數表達式求值* 直接調用Calculator的類方法conversion() * 傳入算數表達式,將返回一個浮點值結果* 如果計算過程錯誤,將返回一個NaN */public class Calculator {private Stack<String> postfixStack = new Stack<String>();// 後綴式棧private Stack<Character> opStack = new Stack<Character>();// 運算符棧private int[] operatPriority = new int[] { 0, 3, 2, 1, -1, 1, 0, 2 };// 運用運算符ASCII碼-40做索引的運算符優先級public static double conversion(String expression) {double result = 0;Calculator cal = new Calculator();try {expression = transform(expression);result = cal.calculate(expression);}catch (Exception e) {// e.printStackTrace();// 運算錯誤返回NaNreturn 0.0 / 0.0;}// return new String().valueOf(result);return result;}/** * 將表達式中負數的符號更改* * @param expression * 例如-2+-1*(-3E-2)-(-1) 被轉為~2+~1*(~3E~2)-(~1) * @return */private static String transform(String expression) {char[] arr = expression.toCharArray();for (int i = 0; i < arr.length; i++) {if (arr[i] == '-') {if (i == 0) {arr[i] = '~';} else {char c = arr[i - 1];if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == 'E' || c == 'e') {arr[i] = '~';}}}}if(arr[0]=='~'||arr[1]=='('){arr[0]='-';return "0"+new String(arr);} else{return new String(arr);}}/** * 按照給定的表達式計算* * @param expression * 要計算的表達式例如:5+12*(3+5)/7 * @return */public double calculate(String expression) {Stack<String> resultStack = new Stack<String>();prepare(expression);Collections.reverse(postfixStack);// 將後綴式棧反轉String firstValue, secondValue, currentValue;// 參與計算的第一個值,第二個值和算術運算符while (!postfixStack.isEmpty()) {currentValue = postfixStack.pop();if (!isOperator(currentValue.charAt(0))) {// 如果不是運算符則存入操作數棧中currentValue = currentValue.replace("~", "-");resultStack.push(currentValue);} else {// 如果是運算符則從操作數棧中取兩個值和該數值一起參與運算secondValue = resultStack.pop();firstValue = resultStack.pop();// 將負數標記符改為負號firstValue = firstValue.replace("~", "-");secondValue = secondValue.replace("~", "-");String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0));resultStack.push(tempResult);}}return double.valueOf(resultStack.pop());}/** * 數據準備階段將表達式轉換成為後綴式棧* * @param expression */private void prepare(String expression) {opStack.push(',');// 運算符放入棧底元素逗號,此符號優先級最低char[] arr = expression.toCharArray();int currentIndex = 0;// 當前字符的位置int count = 0;// 上次算術運算符到本次算術運算符的字符的長度便於或者之間的數值char currentOp, peekOp;// 當前操作符和棧頂操作符for (int i = 0; i < arr.length; i++) {currentOp = arr[i];if (isOperator(currentOp)) {// 如果當前字符是運算符if (count > 0) {postfixStack.push(new String(arr, currentIndex, count));// 取兩個運算符之間的數字}peekOp = opStack.peek();if (currentOp == ')') {// 遇到反括號則將運算符棧中的元素移除到後綴式棧中直到遇到左括號while (opStack.peek() != '(') {postfixStack.push(String.valueOf(opStack.pop()));}opStack.pop();} else {while (currentOp != '(' && peekOp != ',' && compare(currentOp, peekOp)) {postfixStack.push(String.valueOf(opStack.pop()));peekOp = opStack.peek();}opStack.push(currentOp);}count = 0;currentIndex = i + 1;} else {count++;}}if (count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {// 最後一個字符不是括號或者其他運算符的則加入後綴式棧中postfixStack.push(new String(arr, currentIndex, count));}while (opStack.peek() != ',') {postfixStack.push(String.valueOf(opStack.pop()));// 將操作符棧中的剩餘的元素添加到後綴式棧中}}/** * 判斷是否為算術符號* * @param c * @return */private Boolean isOperator(char c) {return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';}/** * 利用ASCII碼-40做下標去算術符號優先級* * @param cur * @param peek * @return */public Boolean compare(char cur, char peek) {// 如果是peek優先級高於cur,返回true,默認都是peek優先級要低Boolean result = false;if (operatPriority[(peek) - 40] >= operatPriority[(cur) - 40]) {result = true;}return result;}/** * 按照給定的算術運算符做計算* * @param firstValue * @param secondValue * @param currentOp * @return */private String calculate(String firstValue, String secondValue, char currentOp) {String result = "";switch (currentOp) {case '+': result = String.valueOf(ArithHelper.add(firstValue, secondValue));break;case '-': result = String.valueOf(ArithHelper.sub(firstValue, secondValue));break;case '*': result = String.valueOf(ArithHelper.mul(firstValue, secondValue));break;case '/': result = String.valueOf(ArithHelper.div(firstValue, secondValue));break;}return result;}}ArithHelper 代碼如下:
public class ArithHelper {// 默認除法運算精度private static final int DEF_DIV_SCALE = 16;// 這個類不能實例化private ArithHelper() {}/** * 提供精確的加法運算。 * * @param v1 被加數* @param v2 加數* @return 兩個參數的和*/public static double add(double v1, double v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(double.toString(v1));java.math.BigDecimal b2 = new java.math.BigDecimal(double.toString(v2));return b1.add(b2).doubleValue();}public static double add(String v1, String v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(v1);java.math.BigDecimal b2 = new java.math.BigDecimal(v2);return b1.add(b2).doubleValue();}/** * 提供精確的減法運算。 * * @param v1 被減數* @param v2 減數* @return 兩個參數的差*/public static double sub(double v1, double v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(double.toString(v1));java.math.BigDecimal b2 = new java.math.BigDecimal(double.toString(v2));return b1.subtract(b2).doubleValue();}public static double sub(String v1, String v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(v1);java.math.BigDecimal b2 = new java.math.BigDecimal(v2);return b1.subtract(b2).doubleValue();}/** * 提供精確的乘法運算。 * * @param v1 * 被乘數* @param v2 * 乘數* @return 兩個參數的積*/public static double mul(double v1, double v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(double.toString(v1));java.math.BigDecimal b2 = new java.math.BigDecimal(double.toString(v2));return b1.multiply(b2).doubleValue();}public static double mul(String v1, String v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(v1);java.math.BigDecimal b2 = new java.math.BigDecimal(v2);return b1.multiply(b2).doubleValue();}/** * 提供(相對)精確的除法運算,當發生除不盡的情況時,精確到小數點以後10位,以後的數字四捨五入。 * * @param v1 * 被除數* @param v2 * 除數* @return 兩個參數的商*/public static double div(double v1, double v2) {return div(v1, v2, DEF_DIV_SCALE);}public static double div(String v1, String v2) {java.math.BigDecimal b1 = new java.math.BigDecimal(v1);java.math.BigDecimal b2 = new java.math.BigDecimal(v2);return b1.divide(b2, DEF_DIV_SCALE, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}/** * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale參數指定精度,以後的數字四捨五入。 * * @param v1 被除數* @param v2 除數* @param scale 表示表示需要精確到小數點以後幾位。 * @return 兩個參數的商*/public static double div(double v1, double v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}java.math.BigDecimal b1 = new java.math.BigDecimal(double.toString(v1));java.math.BigDecimal b2 = new java.math.BigDecimal(double.toString(v2));return b1.divide(b2, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}/** * 提供精確的小數位四捨五入處理。 * * @param v 需要四捨五入的數字* @param scale 小數點後保留幾位* @return 四捨五入後的結果*/public static double round(double v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}java.math.BigDecimal b = new java.math.BigDecimal(double.toString(v));java.math.BigDecimal one = new java.math.BigDecimal("1");return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}public static double round(String v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}java.math.BigDecimal b = new java.math.BigDecimal(v);java.math.BigDecimal one = new java.math.BigDecimal("1");return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}}使用時調用Calculator 類的conversion()方法,並傳入算術表達式參數,即可返回一個Double 類型的值。
使用示例:
public class MathTest {public static void main(String[] args) {String expression = "(0*1--3)-5/-4-(3*(-2.13))";double result = Calculator.conversion(expression);System.out.println(expression + " = " + result);System.out.println();}}控制台輸出:
(0*1--3)-5/-4-(3*(-2.13)) = 10.64
測試截圖:
總結
以上就是本文關於Java計算數學表達式代碼詳解的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!