v1.8 代码完成解耦

pull/6/head
杨博文 7 months ago
parent 641b44d8f6
commit 9f91a754b0

@ -32,7 +32,8 @@ import java.util.Stack;
*/
public class AdvancedCaculate {
private static final Set<String> OPERATORS = new HashSet<>(Arrays.asList("+", "-", "*", "/"));
private static final Set<String> BASIC_OPERATORS = new HashSet<>(
Arrays.asList("+", "-", "*", "/"));
private static final Set<String> ADVANCED_OPERATORS = new HashSet<>(
Arrays.asList("平方", "开根号", "sin", "cos", "tan"));
private static final Map<String, Integer> PRECEDENCE = new HashMap<>();
@ -64,42 +65,17 @@ public class AdvancedCaculate {
Stack<Double> numberStack = new Stack<>();
Stack<String> operatorStack = new Stack<>();
for (int i = 0; i < expressionTokens.size(); i++) {
String token = expressionTokens.get(i);
for (String token : expressionTokens) {
if (isNumeric(token)) {
numberStack.push(Double.parseDouble(token));
} else if (token.equals("(")) {
operatorStack.push(token);
} else if (token.equals(")")) {
while (!operatorStack.isEmpty() && !operatorStack.peek().equals("(")) {
processOperator(numberStack, operatorStack.pop());
}
if (!operatorStack.isEmpty()) { // Pop the "("
operatorStack.pop();
}
handleClosingParenthesis(numberStack, operatorStack);
} else if (ADVANCED_OPERATORS.contains(token)) {
// 前置运算符 (开根号, sin, cos, tan) 直接入栈
// 后置运算符 (平方) 需要等待其操作数先计算出来
// 在标准调度场算法中,后置运算符通常在遇到时立即处理其栈顶的操作数
// 这里我们可以在遇到 "平方" 时,立即对 numberStack 的顶部元素进行平方操作
if ("平方".equals(token)) {
if (numberStack.isEmpty()) {
throw new IllegalArgumentException("Invalid expression: '平方' lacks an operand.");
}
double operand = numberStack.pop();
numberStack.push(Math.pow(operand, 2));
} else { // "开根号", "sin", "cos", "tan" 是前置运算符
operatorStack.push(token);
}
} else if (OPERATORS.contains(token)) {
// 处理四则运算符,遵循优先级
while (!operatorStack.isEmpty() &&
!operatorStack.peek().equals("(") &&
PRECEDENCE.get(token) <= PRECEDENCE.getOrDefault(operatorStack.peek(), 0)) {
processOperator(numberStack, operatorStack.pop());
}
operatorStack.push(token);
handleAdvancedOperator(token, numberStack, operatorStack);
} else if (BASIC_OPERATORS.contains(token)) {
handleBasicOperator(token, numberStack, operatorStack);
} else {
throw new IllegalArgumentException("Unknown token: " + token);
}
@ -118,10 +94,54 @@ public class AdvancedCaculate {
throw new IllegalArgumentException(
"Invalid expression: " + String.join(" ", expressionTokens));
}
return numberStack.pop();
}
/**
* ')'
*/
private static void handleClosingParenthesis(Stack<Double> numberStack,
Stack<String> operatorStack) {
while (!operatorStack.isEmpty() && !operatorStack.peek().equals("(")) {
processOperator(numberStack, operatorStack.pop());
}
if (!operatorStack.isEmpty()) { // Pop the "("
operatorStack.pop();
} else {
throw new IllegalArgumentException("Mismatched parentheses in expression.");
}
}
/**
* , sin, cos, tan,
*/
private static void handleAdvancedOperator(String token, Stack<Double> numberStack,
Stack<String> operatorStack) {
if ("平方".equals(token)) {
if (numberStack.isEmpty()) {
throw new IllegalArgumentException("Invalid expression: '平方' lacks an operand.");
}
double operand = numberStack.pop();
numberStack.push(Math.pow(operand, 2));
} else { // "开根号", "sin", "cos", "tan" 是前置运算符
operatorStack.push(token);
}
}
/**
* +, -, *, /
*/
private static void handleBasicOperator(String token, Stack<Double> numberStack,
Stack<String> operatorStack) {
// 处理四则运算符,遵循优先级
while (!operatorStack.isEmpty() &&
!operatorStack.peek().equals("(") &&
PRECEDENCE.get(token) <= PRECEDENCE.getOrDefault(operatorStack.peek(), 0)) {
processOperator(numberStack, operatorStack.pop());
}
operatorStack.push(token);
}
/**
*
*
@ -131,67 +151,83 @@ public class AdvancedCaculate {
* @throws ArithmeticException
*/
private static void processOperator(Stack<Double> numberStack, String operator) {
if (numberStack.size() < 1) {
if (numberStack.isEmpty()) {
throw new IllegalArgumentException(
"Invalid expression: operator '" + operator + "' lacks operand(s).");
}
if (ADVANCED_OPERATORS.contains(operator)) {
double operand = numberStack.pop();
switch (operator) {
case "开根号":
if (operand < 0) {
// 抛出异常让调用者MultipleChoiceGenerator处理
throw new ArithmeticException("Cannot take square root of negative number: " + operand);
}
numberStack.push(Math.sqrt(operand));
break;
case "sin":
numberStack.push(Math.sin(Math.toRadians(operand))); // 假设输入是度数
break;
case "cos":
numberStack.push(Math.cos(Math.toRadians(operand)));
break;
case "tan":
// tan(90 + n*180) 会趋向无穷,这里不特别处理,让其返回 Infinity 或 -Infinity
numberStack.push(Math.tan(Math.toRadians(operand)));
break;
default:
throw new IllegalArgumentException("Unknown advanced operator: " + operator);
}
} else if (OPERATORS.contains(operator)) {
if (numberStack.size() < 2) {
throw new IllegalArgumentException(
"Invalid expression: operator '" + operator + "' lacks operand(s).");
}
double b = numberStack.pop();
double a = numberStack.pop();
double result;
switch (operator) {
case "+":
result = a + b;
break;
case "-":
result = a - b;
break;
case "*":
result = a * b;
break;
case "/":
if (b == 0) {
throw new ArithmeticException("Division by zero");
}
result = a / b;
break;
default:
throw new IllegalArgumentException("Unknown operator: " + operator);
}
numberStack.push(result);
processAdvancedOperator(numberStack, operator);
} else if (BASIC_OPERATORS.contains(operator)) {
processBasicOperator(numberStack, operator);
} else {
throw new IllegalArgumentException("Unexpected operator in process: " + operator);
}
}
/**
* , sin, cos, tan
*/
private static void processAdvancedOperator(Stack<Double> numberStack, String operator) {
double operand = numberStack.pop();
double result;
switch (operator) {
case "开根号":
if (operand < 0) {
// 抛出异常让调用者MultipleChoiceGenerator处理
throw new ArithmeticException("Cannot take square root of negative number: " + operand);
}
result = Math.sqrt(operand);
break;
case "sin":
result = Math.sin(Math.toRadians(operand)); // 假设输入是度数
break;
case "cos":
result = Math.cos(Math.toRadians(operand));
break;
case "tan":
// tan(90 + n*180) 会趋向无穷,这里不特别处理,让其返回 Infinity 或 -Infinity
result = Math.tan(Math.toRadians(operand));
break;
default:
throw new IllegalArgumentException("Unknown advanced operator: " + operator);
}
numberStack.push(result);
}
/**
* +, -, *, /
*/
private static void processBasicOperator(Stack<Double> numberStack, String operator) {
if (numberStack.size() < 2) {
throw new IllegalArgumentException(
"Invalid expression: operator '" + operator + "' lacks operand(s).");
}
double b = numberStack.pop();
double a = numberStack.pop();
double result;
switch (operator) {
case "+":
result = a + b;
break;
case "-":
result = a - b;
break;
case "*":
result = a * b;
break;
case "/":
if (b == 0) {
throw new ArithmeticException("Division by zero");
}
result = a / b;
break;
default:
throw new IllegalArgumentException("Unknown operator: " + operator);
}
numberStack.push(result);
}
/**
*
*

Loading…
Cancel
Save