這篇文章主要為大家展示了“Java如何計(jì)算數(shù)學(xué)表達(dá)式”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Java如何計(jì)算數(shù)學(xué)表達(dá)式”這篇文章吧。
創(chuàng)新互聯(lián)建站,專注為中小企業(yè)提供官網(wǎng)建設(shè)、營(yíng)銷型網(wǎng)站制作、自適應(yīng)網(wǎng)站建設(shè)、展示型成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)等服務(wù),幫助中小企業(yè)通過(guò)網(wǎng)站體現(xiàn)價(jià)值、有效益。幫助企業(yè)快速建站、解決網(wǎng)站建設(shè)與網(wǎng)站營(yíng)銷推廣問(wèn)題。
Java字符串轉(zhuǎn)換成算術(shù)表達(dá)式計(jì)算并輸出結(jié)果,通過(guò)這個(gè)工具可以直接對(duì)字符串形式的算術(shù)表達(dá)式進(jìn)行運(yùn)算,并且使用非常簡(jiǎn)單。
這個(gè)工具中包含兩個(gè)類 Calculator 和 ArithHelper
Calculator 代碼如下:
import java.util.Collections; import java.util.Stack; /** * 算數(shù)表達(dá)式求值 * 直接調(diào)用Calculator的類方法conversion() * 傳入算數(shù)表達(dá)式,將返回一個(gè)浮點(diǎn)值結(jié)果 * 如果計(jì)算過(guò)程錯(cuò)誤,將返回一個(gè)NaN */ public class Calculator { private StackpostfixStack = new Stack (); // 后綴式棧 private Stack opStack = new Stack (); // 運(yùn)算符棧 private int[] operatPriority = new int[] { 0, 3, 2, 1, -1, 1, 0, 2 }; // 運(yùn)用運(yùn)算符ASCII碼-40做索引的運(yùn)算符優(yōu)先級(jí) 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(); // 運(yùn)算錯(cuò)誤返回NaN return 0.0 / 0.0; } // return new String().valueOf(result); return result; } /** * 將表達(dá)式中負(fù)數(shù)的符號(hào)更改 * * @param expression * 例如-2+-1*(-3E-2)-(-1) 被轉(zhuǎn)為 ~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); } } /** * 按照給定的表達(dá)式計(jì)算 * * @param expression * 要計(jì)算的表達(dá)式例如:5+12*(3+5)/7 * @return */ public double calculate(String expression) { Stack resultStack = new Stack (); prepare(expression); Collections.reverse(postfixStack); // 將后綴式棧反轉(zhuǎn) String firstValue, secondValue, currentValue; // 參與計(jì)算的第一個(gè)值,第二個(gè)值和算術(shù)運(yùn)算符 while (!postfixStack.isEmpty()) { currentValue = postfixStack.pop(); if (!isOperator(currentValue.charAt(0))) { // 如果不是運(yùn)算符則存入操作數(shù)棧中 currentValue = currentValue.replace("~", "-"); resultStack.push(currentValue); } else { // 如果是運(yùn)算符則從操作數(shù)棧中取兩個(gè)值和該數(shù)值一起參與運(yùn)算 secondValue = resultStack.pop(); firstValue = resultStack.pop(); // 將負(fù)數(shù)標(biāo)記符改為負(fù)號(hào) firstValue = firstValue.replace("~", "-"); secondValue = secondValue.replace("~", "-"); String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0)); resultStack.push(tempResult); } } return double.valueOf(resultStack.pop()); } /** * 數(shù)據(jù)準(zhǔn)備階段將表達(dá)式轉(zhuǎn)換成為后綴式棧 * * @param expression */ private void prepare(String expression) { opStack.push(','); // 運(yùn)算符放入棧底元素逗號(hào),此符號(hào)優(yōu)先級(jí)最低 char[] arr = expression.toCharArray(); int currentIndex = 0; // 當(dāng)前字符的位置 int count = 0; // 上次算術(shù)運(yùn)算符到本次算術(shù)運(yùn)算符的字符的長(zhǎng)度便于或者之間的數(shù)值 char currentOp, peekOp; // 當(dāng)前操作符和棧頂操作符 for (int i = 0; i < arr.length; i++) { currentOp = arr[i]; if (isOperator(currentOp)) { // 如果當(dāng)前字符是運(yùn)算符 if (count > 0) { postfixStack.push(new String(arr, currentIndex, count)); // 取兩個(gè)運(yùn)算符之間的數(shù)字 } peekOp = opStack.peek(); if (currentOp == ')') { // 遇到反括號(hào)則將運(yùn)算符棧中的元素移除到后綴式棧中直到遇到左括號(hào) 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]))) { // 最后一個(gè)字符不是括號(hào)或者其他運(yùn)算符的則加入后綴式棧中 postfixStack.push(new String(arr, currentIndex, count)); } while (opStack.peek() != ',') { postfixStack.push(String.valueOf(opStack.pop())); // 將操作符棧中的剩余的元素添加到后綴式棧中 } } /** * 判斷是否為算術(shù)符號(hào) * * @param c * @return */ private Boolean isOperator(char c) { return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')'; } /** * 利用ASCII碼-40做下標(biāo)去算術(shù)符號(hào)優(yōu)先級(jí) * * @param cur * @param peek * @return */ public Boolean compare(char cur, char peek) { // 如果是peek優(yōu)先級(jí)高于cur,返回true,默認(rèn)都是peek優(yōu)先級(jí)要低 Boolean result = false; if (operatPriority[(peek) - 40] >= operatPriority[(cur) - 40]) { result = true; } return result; } /** * 按照給定的算術(shù)運(yùn)算符做計(jì)算 * * @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 { // 默認(rèn)除法運(yùn)算精度 private static final int DEF_DIV_SCALE = 16; // 這個(gè)類不能實(shí)例化 private ArithHelper() { } /** * 提供精確的加法運(yùn)算。 * * @param v1 被加數(shù) * @param v2 加數(shù) * @return 兩個(gè)參數(shù)的和 */ 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(); } /** * 提供精確的減法運(yùn)算。 * * @param v1 被減數(shù) * @param v2 減數(shù) * @return 兩個(gè)參數(shù)的差 */ 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(); } /** * 提供精確的乘法運(yùn)算。 * * @param v1 * 被乘數(shù) * @param v2 * 乘數(shù) * @return 兩個(gè)參數(shù)的積 */ 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(); } /** * 提供(相對(duì))精確的除法運(yùn)算,當(dāng)發(fā)生除不盡的情況時(shí),精確到 小數(shù)點(diǎn)以后10位,以后的數(shù)字四舍五入。 * * @param v1 * 被除數(shù) * @param v2 * 除數(shù) * @return 兩個(gè)參數(shù)的商 */ 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(); } /** * 提供(相對(duì))精確的除法運(yùn)算。當(dāng)發(fā)生除不盡的情況時(shí),由scale參數(shù)指 定精度,以后的數(shù)字四舍五入。 * * @param v1 被除數(shù) * @param v2 除數(shù) * @param scale 表示表示需要精確到小數(shù)點(diǎn)以后幾位。 * @return 兩個(gè)參數(shù)的商 */ 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(); } /** * 提供精確的小數(shù)位四舍五入處理。 * * @param v 需要四舍五入的數(shù)字 * @param scale 小數(shù)點(diǎn)后保留幾位 * @return 四舍五入后的結(jié)果 */ 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(); } }
使用時(shí)調(diào)用 Calculator 類的 conversion()方法,并傳入算術(shù)表達(dá)式參數(shù),即可返回一個(gè) 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(); } }
控制臺(tái)輸出:
(0*1--3)-5/-4-(3*(-2.13)) = 10.64
測(cè)試截圖:
以上是“Java如何計(jì)算數(shù)學(xué)表達(dá)式”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!