修复题目生成bug

liwentao_branch
Teptao 4 months ago
parent 381900b80d
commit 65fa0802ee

@ -63,7 +63,9 @@ public abstract class AbstractProblemGenerator implements IProblemGenerator {
addOperandAndOperator(operands, operators, operator, nonNegativeOnly);
}
addParentheses(operands, operators);
if(nonNegativeOnly) {
addParentheses(operands, operators);
}
return new Equation(operands, operators);
}

@ -4,47 +4,74 @@ import com.mathapp.models.Equation;
import com.mathapp.models.Operator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* /
*
* exp4j
*
*
*/
public class HighSchoolProblemGenerator extends MiddleSchoolProblemGenerator {
private static final int[] PREDEFINED_ANGLES = new int[]{0, 30, 45, 60, 90};
private static final String[] TRIG_FUNCTIONS = new String[]{"sin", "cos", "tan"};
private static final int[] PREDEFINED_ANGLES = {0, 30, 45, 60, 90};
private static final String[] TRIG_FUNCTIONS = {"sin", "cos", "tan"};
@Override
protected Equation createProblem() {
// 复用初中生成器的逻辑,先生成一个带平方或开方的题目
// 1. 调用父类方法生成一个包含平方或开方的基础题目
Equation middleSchoolEquation = super.createProblem();
List<String> operands = new ArrayList<>(middleSchoolEquation.operands());
List<Operator> operators = new ArrayList<>(middleSchoolEquation.operators());
String function = Arrays.toString(TRIG_FUNCTIONS);
int[] angle = PREDEFINED_ANGLES;
String trigExpression;
Operator connectingOperator;
// 生成对学生友好的三角函数表达式,如 "sin(30)"
// exp4j 的计算将在 QuestionGenerator 中通过自定义函数处理角度
String trigExpression = String.format("%s(%d)", function, angle);
// 2.【最终修正策略】使用健壮性检查循环,直到生成一个绝对安全的组合
while (true) {
// 2a. 生成三角函数部分,并确保它不是 tan(90°)
String function;
int angleInDegrees;
do {
function = TRIG_FUNCTIONS[random.nextInt(TRIG_FUNCTIONS.length)];
angleInDegrees = PREDEFINED_ANGLES[random.nextInt(PREDEFINED_ANGLES.length)];
} while (function.equals("tan") && angleInDegrees == 90);
// 随机选择一个位置插入三角函数表达式
int insertPos = random.nextInt(operands.size() + 1);
if (insertPos == operands.size() || operands.isEmpty()) {
operands.add(trigExpression);
if(!operators.isEmpty() || operands.size() > 1) {
operators.add(Operator.ADD);
trigExpression = String.format("%s(%s)", function, getRadianString(angleInDegrees));
// 2b. 随机选择一个连接运算符
connectingOperator = Operator.values()[random.nextInt(Operator.values().length)];
// 2c.【健壮性检查】检查这个新运算符是否会与三角函数的值构成除零错误
boolean isTrigValueZero = (function.equals("sin") && angleInDegrees == 0) ||
(function.equals("tan") && angleInDegrees == 0);
// 如果新运算符是除法且三角函数的值是0则这是一个非法组合必须重试
if (connectingOperator == Operator.DIVIDE && isTrigValueZero) {
continue; // 非法组合,重新循环
}
} else {
operands.add(insertPos, trigExpression);
operators.add(insertPos, Operator.ADD); // 简单地用加法连接
// 如果代码能执行到这里,说明组合是安全的,可以退出循环
break;
}
// 3.【安全的追加操作】将生成的安全组合追加到表达式末尾
// 这种方法永远不会导致 IndexOutOfBoundsException
operands.add(trigExpression);
operators.add(connectingOperator);
return new Equation(operands, operators);
}
/**
* exp4j pi
*/
private String getRadianString(int angleInDegrees) {
switch (angleInDegrees) {
case 0: return "0";
case 30: return "pi/6";
case 45: return "pi/4";
case 60: return "pi/3";
case 90: return "pi/2";
default: return "0";
}
}
}

@ -8,34 +8,38 @@ import java.util.List;
/**
*
*
* exp4j
* (, "(5^2)" "sqrt(25)") exp4j
*/
public class MiddleSchoolProblemGenerator extends AbstractProblemGenerator {
@Override
protected Equation createProblem() {
// 1. 调用父类的核心方法,并传入 false允许生成包含负数的标准表达式。
Equation basicEquation = createBaseArithmeticProblem(false);
// 2. 将基础表达式元素转为可修改的列表
List<String> operands = new ArrayList<>(basicEquation.operands());
List<Operator> operators = new ArrayList<>(basicEquation.operators());
// 3. 随机选择一个操作数进行变形
int modifyIndex = random.nextInt(operands.size());
String targetOperand = operands.get(modifyIndex);
// 检查操作数是否已经是复杂表达式(包含括号),如果是,则不再添加括号
boolean isComplex = targetOperand.contains("(") && targetOperand.contains(")");
String targetOperand = operands.get(modifyIndex).replace("(", "").replace(")", "");
// 4. 随机决定是进行平方还是开方运算
if (random.nextBoolean()) {
// 平方运算exp4j 使用 '^' 符号
// 如果操作数本身是复杂表达式,如 (3+2),则需要保留括号,变成 ((3+2)^2)
String squaredExpression = isComplex? String.format("(%s^2)", targetOperand) : String.format("%s^2", targetOperand);
// 平方运算: 使用 `^` 符号exp4j 支持此格式
String squaredExpression = String.format("(%s^2)", targetOperand);
operands.set(modifyIndex, squaredExpression);
} else {
// 开方运算exp4j 使用 'sqrt()' 函数
// 开方运算: 使用 `sqrt()` 函数exp4j 内置支持此函数
int base = getRandomNumber(2, 10);
int valueToRoot = base * base;
String sqrtExpression = String.format("sqrt(%d)", valueToRoot);
operands.set(modifyIndex, sqrtExpression);
}
// 5. 返回构建好的、与exp4j兼容的方程式
return new Equation(operands, operators);
}
}

Loading…
Cancel
Save