JAVA字符串数学公式运算-辅助类-支持浮点数错误纠正-低消耗-高可用性-小数点后面保留16位小数
生活随笔
收集整理的這篇文章主要介紹了
JAVA字符串数学公式运算-辅助类-支持浮点数错误纠正-低消耗-高可用性-小数点后面保留16位小数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
//計算輔助類·基礎計算
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();} }//邏輯處理
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;} }
調用測試
public class Test {public static void main(String[] args) {long start = System.currentTimeMillis();for (int i = 0; i < 1000; i++) {String expression = "(5+51231+51+3+57*37+52+7*53+7+53+7/53)";double result = Calculator.conversion(expression);System.out.println(expression + " = " + result);}long end = System.currentTimeMillis();System.out.println("1000次計算平均耗時消耗時間:" + ((end - start)/100) + "毫秒");} }
1000次運算平均耗時1毫秒,完全符合企業級標準,可以應用。
并且處理了例如1.2-1=0.1999999999999999這種浮點數運算錯誤。
總結
以上是生活随笔為你收集整理的JAVA字符串数学公式运算-辅助类-支持浮点数错误纠正-低消耗-高可用性-小数点后面保留16位小数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .Net 下载网络图片
- 下一篇: 大专普通本科、搞算法的(蓝桥杯、ACM、