java用栈处理四则运算_Java 用栈处理四则运算
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 目前只能做簡單的四則運算,不支持浮點數和其他符號,不支持多線程
* 計算步驟:
* 1.中輟表達式轉后綴
* 2.計算后綴表達式
*/
public class Arithmetic {
/** 錯誤提示 **/
private static final String ERROR_ZERO = "DividedZero";
/** 檢測一個字符串是不是數字 **/
private static Pattern pattern = Pattern.compile("\\d+\\.?\\d?");
/** 運算符優先級 **/
private static Map priority = new HashMap<>();
static {
priority.put("*", 2);
priority.put("/", 2);
priority.put("+", 1);
priority.put("-", 1);
priority.put("", -1); // 無運算符
}
/** 替換表達式中的中文括號 **/
private static Map replace = new HashMap<>();
static {
replace.put("(", "(");
replace.put(")", ")");
}
/** 支持的運算符 **/
private static String[] operator = {"+", "-", "*", "/"};
private static Stack stack = new Stack<>();
/**
* -----------測試代碼----------------
*/
public static void main(String[] args) {
String expression = "8+(9-1)*8+7/2";
System.out.println(execute(expression));
}
/**
* 整個計算過程
* @param expression 傳入的表達式
* @return 計算結果
*/
public static String execute(String expression) {
return suffixToValue(inffixToSuffix(trim(expression)));
}
/**
* 整理算式,替換掉中文括號等
* @param expression 算式
* @return 整理后的算式
*/
private static String trim(String expression) {
String result = expression.trim();
for (Map.Entry entry : replace.entrySet()) {
result = result.replace(entry.getKey(), entry.getValue());
}
return result;
}
/**
* 將中綴表達式轉換成后綴表達式
* eg:中綴表達式8+(9-1)*8+7/2
* 后綴表達式8 9 1 - 8 * + 7 2 / +,元素之間之間用空格分隔。
* 從左到右遍歷中綴表達式的每一個數字和運算符
* 如果數字就輸出(即存入后綴表達式)
* 如果是右括號,則彈出左括號之前的運算符
* 如果優先級低于棧頂運算符,則彈出棧頂運算符,并將當前運算符進棧
* 遍歷結束后,將棧則剩余運算符彈出。
* @param expression 中綴表達式
* @return 后綴表達式
*/
private static String inffixToSuffix(String expression) {
stack.clear();
StringBuilder inffix = new StringBuilder(expression);
StringBuilder suffix = new StringBuilder();
String element = ""; // 中綴表達式的數字或者運算符
String tmp = "";
while (inffix.length() > 0) {
element = popNextElement(inffix);
if (isNum(element)) { // 是數字則輸出
suffix.append(element).append(" ");
} else if (")".equals(element)) { // 右括號則將左括號之前的內容全彈出
tmp = stack.pop();
while (!"(".equals(tmp)) {
suffix.append(tmp).append(" ");
tmp = stack.pop();
}
} else if ("(".equals(element) || priority.get(element) >= priority.get(getTopOperator())) {
stack.push(element);
} else { // 優先級小于棧頂運算符,則彈出
tmp = stack.pop();
suffix.append(tmp).append(" ").append(element).append(" ");
}
}
// 把棧中剩余運算符都彈出
while (stack.size() > 0) {
suffix.append(stack.pop()).append(" ");
}
return suffix.toString();
}
/**
* 根據后綴表達式算出結果
* eg:中綴表達式8+(9-1)*8+7/2
* 后綴表達式8 9 1 - 8 * + 7 2 / +,元素之間之間用空格分隔。
* 從左到右遍歷后綴表達式
* 遇到數字就進棧
* 遇到符號,就將棧頂的兩個數字出棧運算,運算結果進棧,直到獲得最終結果。
* -----------目前只支持整數,由于整數相除會出現浮點數,這里用String作為返回值--------
* @param expression 后綴表達式
* @return 結果
*/
private static String suffixToValue(String expression) {
// 已經用空格分隔,直接分割
String[] suffix = expression.split(" ");
stack.clear();
double num1 = 0, num2 = 0; // 注意次序,num2在棧頂,整數運算結果也可能是double
String tmp = "";
for (int i = 0; i < suffix.length; i++) {
if (isNum(suffix[i])) { // 數字
stack.push(suffix[i]);
} else{ // 是操作符
num2 = Double.parseDouble(stack.pop());
num1 = Double.parseDouble(stack.pop());
tmp = calculate(num1, num2, suffix[i]);
if (ERROR_ZERO.equals(tmp)) {
throw new ArithmeticException("被除數不能為0");
} else {
stack.push(tmp);
}
}
}
// 最終結果也壓在棧中,取出即可
return stack.pop();
}
/**
* 目前只支持整數,但是整數運算結果也可能是double,故這里傳入的參數用double。
* @param num1 第一個數,在前
* @param num2 第二個數,在后
* @param operator 運算符
* @return 運算結果,除數為0則返回Error
*/
private static String calculate(double num1, double num2, String operator) {
double result = 0;
switch (operator) {
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "*":
result = num1 * num2;
break;
case "/":
if (num2 == 0){ // 除數為0
return ERROR_ZERO;
}
result = 1.0 * num1 / num2;
break;
default:
break;
}
return String.valueOf(result);
}
/**
* 檢測字符是不是數字
* 浮點數其實可以寫零寬斷言,但是
* @param c 待檢測字符
* @return 檢測結果
*/
private static boolean isNum(char c) {
if ( (c >= '0' && c <= '9') || c == '.' ) {
return true;
}
return false;
}
/**
* 檢測字符串是不是數字
* @param str 待檢測字符串
* @return 檢測結果
*/
private static boolean isNum(String str) {
Matcher matcher = pattern.matcher(str);
if (matcher.matches()) {
return true;
}
return false;
}
/**
* 獲取棧頂運算符
* @return 如果棧中無運算符,則返回空字符串
*/
private static String getTopOperator() {
String tmp = "";
for (int i = stack.size() - 1; i >= 0; i--) {
tmp = stack.get(i);
if ("(".equals(tmp)) {
break;
} else if (isOperator(tmp)) {
return tmp;
}
}
return "";
}
/**
* 檢測一個字符是不是運算符
* 棧中不是運算符就是括號
* @param str 待檢測字符,由于可能有多位數字字符串,這里用的是String
* @return 檢測結果
*/
private static boolean isOperator(String str) {
for (int i = 0; i < operator.length; i++) {
if (operator[i].equals(str)) {
return true;
}
}
return false;
// // 也可以如下:
// return Arrays.asList(operator).contains(str);
}
/**
* 獲取表達式的下一個運算符或數字,同時從表達式中刪除該元素
* @param expression 表達式
* @return
*/
private static String popNextElement(StringBuilder expression) {
StringBuilder result = new StringBuilder();
char c = expression.charAt(0);
expression.deleteCharAt(0);
result.append(c);
if (isNum(c)) {
// 如果第一次取到的是數字,則繼續檢查
while ( expression.length() >0 && isNum(c = expression.charAt(0))) {
expression.deleteCharAt(0);
result.append(c);
}
}
return result.toString();
}
}
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java用栈处理四则运算_Java 用栈处理四则运算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 决策树模型 - (ID3算法、C4.5算
- 下一篇: ipv6 访问内网_【内网渗透】—— 隐