You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
projectone/AbstractProblemGenerator.java

124 lines
5.1 KiB

import java.text.DecimalFormat;
import java.util.Random;
/**
* 抽象题目生成器:封装公共工具方法与共享状态
*/
public abstract class AbstractProblemGenerator {
protected final Random random;
protected final DecimalFormat df;
protected AbstractProblemGenerator(Random random, DecimalFormat df) {
this.random = random;
this.df = df;
}
/**
* 子类实现具体题目生成逻辑
*/
public abstract MathProblem generate();
// 构建带括号的表达式(只包两个操作数)
protected String buildExpressionWithBrackets(int[] operands, String[] operators, int startPos) {
StringBuilder expression = new StringBuilder();
for (int i = 0; i < operands.length; i++) {
if (i == startPos) {
expression.append("(");
}
expression.append(operands[i]);
if (i == startPos + 1) {
expression.append(")");
}
if (i < operands.length - 1) {
expression.append(" ").append(operators[i]).append(" ");
}
}
return expression.toString();
}
// 计算带括号的表达式结果(只合并两个操作数)
protected double evaluateExpressionWithBrackets(int[] operands, String[] operators, int startPos) {
double bracketResult = applyOperator(operands[startPos], operands[startPos + 1], operators[startPos]);
int newOperandCount = operands.length - 1;
int[] newOperands = new int[newOperandCount];
String[] newOperators = new String[newOperandCount - 1];
for (int i = 0; i < startPos; i++) newOperands[i] = operands[i];
newOperands[startPos] = (int) bracketResult;
for (int i = startPos + 1; i < newOperandCount; i++) newOperands[i] = operands[i + 1];
for (int i = 0; i < newOperandCount - 1; i++) {
if (i < startPos) newOperators[i] = operators[i];
else newOperators[i] = operators[i + 1];
}
double result = newOperands[0];
for (int i = 0; i < newOperandCount - 1; i++) {
result = applyOperator(result, newOperands[i + 1], newOperators[i]);
}
return result;
}
/** 应用运算符(整数右操作数) */
protected double applyOperator(double left, int right, String operator) {
switch (operator) {
case "+": return left + right;
case "-": return left - right;
case "*": return left * right;
case "/": return right != 0 ? left / right : left; // 避免除以零
default: return left;
}
}
/** 计算三角函数值 */
protected double calculateTrigFunction(String function, int angle) {
double radians = Math.toRadians(angle);
switch (function) {
case "sin": return Math.sin(radians);
case "cos": return Math.cos(radians);
case "tan":
if (angle == 90) return Double.POSITIVE_INFINITY; // tan(90°)未定义
return Math.tan(radians);
default: return 0;
}
}
/** Double 版本的运算符应用(用于包含三角函数的计算) */
protected double applyOperatorDouble(double left, double right, String operator) {
switch (operator) {
case "+": return left + right;
case "-": return left - right;
case "*": return left * right;
case "/": return right != 0.0 ? left / right : left; // 避免除以零
default: return left;
}
}
/** 将 int 数组转 double 数组 */
protected double[] toDoubleArray(int[] arr) {
double[] out = new double[arr.length];
for (int i = 0; i < arr.length; i++) out[i] = arr[i];
return out;
}
/**
* 选择括号起始位置:仅当能改变优先级,并且括号内结果不为 0 时返回有效下标,否则返回 -1
*/
protected int findBracketStart(double[] values, String[] operators, double probability) {
if (values == null || operators == null) return -1;
if (values.length <= 3) return -1; // 至少 4 个操作数才有加括号的意义
if (random.nextDouble() >= probability) return -1;
int maxStart = values.length - 2; // 仅包两个操作数
int[] candidateStarts = new int[Math.max(0, maxStart + 1)];
int candidateCount = 0;
for (int s = 0; s <= maxStart; s++) {
boolean insideLow = "+".equals(operators[s]) || "-".equals(operators[s]);
boolean leftHigh = (s - 1) >= 0 && ("*".equals(operators[s - 1]) || "/".equals(operators[s - 1]));
boolean rightHigh = (s + 1) < operators.length && ("*".equals(operators[s + 1]) || "/".equals(operators[s + 1]));
if (insideLow && (leftHigh || rightHigh)) {
candidateStarts[candidateCount++] = s;
}
}
if (candidateCount == 0) return -1;
int candidate = candidateStarts[random.nextInt(candidateCount)];
double bracketResult = applyOperatorDouble(values[candidate], values[candidate + 1], operators[candidate]);
return (bracketResult != 0.0) ? candidate : -1;
}
}