Java字符串轉換成算術表達式計算并輸出結果,通過這個工具可以直接對字符串形式的算術表達式進行運算,并且使用非常簡單。
這個工具中包含兩個類 Calculator 和 ArithHelper
Calculator 代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
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(); // 運算錯誤返回NaN return 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 代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
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 類型的值。
使用示例:
1
2
3
4
5
6
7
8
|
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(); } } |
控制臺輸出:
1
|
( 0 * 1 -- 3 )- 5 /- 4 -( 3 *(- 2.13 )) = 10.64 |
測試截圖:
總結
以上就是本文關于Java計算數學表達式代碼詳解的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
原文鏈接:https://www.cnblogs.com/woider/p/5331391.html