|
|
|
|
@ -91,18 +91,92 @@ public class QuestionGenerator {
|
|
|
|
|
* @return 数学表达式
|
|
|
|
|
*/
|
|
|
|
|
private String generatePrimaryExpression() {
|
|
|
|
|
int termCount = random.nextInt(4) + 2;
|
|
|
|
|
StringBuilder expr = new StringBuilder();
|
|
|
|
|
int termCount = random.nextInt(2) + 2; // 2或3个操作数
|
|
|
|
|
char[] operators = {'+', '-', '*', '/'};
|
|
|
|
|
|
|
|
|
|
expr.append(random.nextInt(100) + 1);
|
|
|
|
|
for (int i = 1; i < termCount; i++) {
|
|
|
|
|
char op = operators[random.nextInt(operators.length)];
|
|
|
|
|
int num = random.nextInt(100) + 1;
|
|
|
|
|
expr.append(" ").append(op).append(" ").append(num);
|
|
|
|
|
int num1 = random.nextInt(100) + 1;
|
|
|
|
|
char op1 = operators[random.nextInt(operators.length)];
|
|
|
|
|
int num2;
|
|
|
|
|
|
|
|
|
|
// 为第一个操作符生成第二个操作数,并确保合法性
|
|
|
|
|
if (op1 == '-') {
|
|
|
|
|
num2 = random.nextInt(num1 + 1); // 确保 num1 >= num2
|
|
|
|
|
} else if (op1 == '/') {
|
|
|
|
|
List<Integer> divisors = getDivisors(num1);
|
|
|
|
|
num2 = divisors.get(random.nextInt(divisors.size()));
|
|
|
|
|
} else { // + or *
|
|
|
|
|
num2 = random.nextInt(20) + 1; // 乘法和加法的数小一点,避免结果过大
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果只有两个操作数,直接返回
|
|
|
|
|
if (termCount == 2) {
|
|
|
|
|
return String.format("%d %c %d", num1, op1, num2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- 如果有三个操作数 ---
|
|
|
|
|
String firstPart = String.format("%d %c %d", num1, op1, num2);
|
|
|
|
|
double interimResult;
|
|
|
|
|
try {
|
|
|
|
|
interimResult = evaluateExpression(firstPart);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 如果第一部分计算出错(理论上不应该),则简化为两项操作
|
|
|
|
|
return firstPart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 确保中间结果为非负整数
|
|
|
|
|
if (interimResult < 0 || interimResult != (int)interimResult) {
|
|
|
|
|
return firstPart; // 不满足条件,提前返回两项操作
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char op2 = operators[random.nextInt(operators.length)];
|
|
|
|
|
int num3;
|
|
|
|
|
|
|
|
|
|
// 为第二个操作符生成第三个操作数,并确保合法性
|
|
|
|
|
if (op2 == '-') {
|
|
|
|
|
num3 = random.nextInt((int) interimResult + 1); // 确保 interimResult >= num3
|
|
|
|
|
} else if (op2 == '/') {
|
|
|
|
|
if (interimResult == 0) { // 除数不能为0
|
|
|
|
|
op2 = '+'; // 将操作符改为加法
|
|
|
|
|
num3 = random.nextInt(20) + 1;
|
|
|
|
|
} else {
|
|
|
|
|
List<Integer> divisors = getDivisors((int)interimResult);
|
|
|
|
|
num3 = divisors.get(random.nextInt(divisors.size()));
|
|
|
|
|
}
|
|
|
|
|
} else { // + or *
|
|
|
|
|
num3 = random.nextInt(20) + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return addBrackets(expr.toString());
|
|
|
|
|
// 随机决定是否以及如何添加括号
|
|
|
|
|
if (random.nextBoolean()) {
|
|
|
|
|
return String.format("(%d %c %d) %c %d", num1, op1, num2, op2, num3);
|
|
|
|
|
} else {
|
|
|
|
|
// 检查第二个操作符优先级是否高于第一个
|
|
|
|
|
if ((op2 == '*' || op2 == '/') && (op1 == '+' || op1 == '-')) {
|
|
|
|
|
return String.format("%d %c (%d %c %d)", num1, op1, num2, op2, num3);
|
|
|
|
|
}
|
|
|
|
|
// 默认无括号或左侧括号
|
|
|
|
|
return String.format("%d %c %d %c %d", num1, op1, num2, op2, num3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取一个数的所有正整数约数
|
|
|
|
|
* @param n 数字
|
|
|
|
|
* @return 约数列表
|
|
|
|
|
*/
|
|
|
|
|
private List<Integer> getDivisors(int n) {
|
|
|
|
|
List<Integer> divisors = new ArrayList<>();
|
|
|
|
|
if (n == 0) {
|
|
|
|
|
divisors.add(1); // 除数不能为0,返回1作为安全值
|
|
|
|
|
return divisors;
|
|
|
|
|
}
|
|
|
|
|
n = Math.abs(n); // 处理可能的负数输入
|
|
|
|
|
for (int i = 1; i <= n; i++) {
|
|
|
|
|
if (n % i == 0) {
|
|
|
|
|
divisors.add(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return divisors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -141,10 +215,10 @@ public class QuestionGenerator {
|
|
|
|
|
* @return 数学表达式
|
|
|
|
|
*/
|
|
|
|
|
private String generateMiddleExpression() {
|
|
|
|
|
int termCount = random.nextInt(4) + 2;
|
|
|
|
|
int termCount = random.nextInt(2) + 2; // 2或3个项
|
|
|
|
|
StringBuilder expr = new StringBuilder();
|
|
|
|
|
char[] operators = {'+', '-', '*', '/'};
|
|
|
|
|
boolean hasPowerOrSqrt = false;
|
|
|
|
|
int specialOpIndex = random.nextInt(termCount); // 随机决定哪一项是特殊运算
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < termCount; i++) {
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
@ -152,29 +226,22 @@ public class QuestionGenerator {
|
|
|
|
|
expr.append(" ").append(op).append(" ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int num = random.nextInt(100) + 1;
|
|
|
|
|
if (i == termCount / 2 && !hasPowerOrSqrt) {
|
|
|
|
|
if (i == specialOpIndex) {
|
|
|
|
|
// 强制生成特殊运算
|
|
|
|
|
if (random.nextBoolean()) {
|
|
|
|
|
// 生成平方运算
|
|
|
|
|
int num = random.nextInt(15) + 1; // 平方的底数小一些
|
|
|
|
|
expr.append("pow(").append(num).append(",2)");
|
|
|
|
|
} else {
|
|
|
|
|
expr.append("sqrt(").append(num).append(")");
|
|
|
|
|
// 生成开方运算, 确保是完全平方数
|
|
|
|
|
int sqrtNum = random.nextInt(10) + 1; // 1-10
|
|
|
|
|
int perfectSquare = sqrtNum * sqrtNum;
|
|
|
|
|
expr.append("(√").append(perfectSquare).append(")");
|
|
|
|
|
}
|
|
|
|
|
hasPowerOrSqrt = true;
|
|
|
|
|
} else {
|
|
|
|
|
expr.append(num);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasPowerOrSqrt) {
|
|
|
|
|
int num = random.nextInt(100) + 1;
|
|
|
|
|
char op = operators[random.nextInt(operators.length)];
|
|
|
|
|
if (random.nextBoolean()) {
|
|
|
|
|
expr.append(" ").append(op).append(" pow(").append(num).append(",2)");
|
|
|
|
|
} else {
|
|
|
|
|
expr.append(" ").append(op).append(" sqrt(").append(num).append(")");
|
|
|
|
|
expr.append(random.nextInt(100) + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return expr.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -184,11 +251,11 @@ public class QuestionGenerator {
|
|
|
|
|
* @return 数学表达式
|
|
|
|
|
*/
|
|
|
|
|
private String generateHighExpression() {
|
|
|
|
|
int termCount = random.nextInt(4) + 2;
|
|
|
|
|
int termCount = random.nextInt(2) + 2; // 2或3个项
|
|
|
|
|
StringBuilder expr = new StringBuilder();
|
|
|
|
|
char[] operators = {'+', '-', '*', '/'};
|
|
|
|
|
String[] functions = {"sin", "cos", "tan"};
|
|
|
|
|
boolean hasTrig = false;
|
|
|
|
|
int trigFuncIndex = random.nextInt(termCount); // 随机决定哪一项是三角函数
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < termCount; i++) {
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
@ -196,24 +263,20 @@ public class QuestionGenerator {
|
|
|
|
|
expr.append(" ").append(op).append(" ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i == termCount / 2 && !hasTrig) {
|
|
|
|
|
if (i == trigFuncIndex) {
|
|
|
|
|
// 强制生成三角函数
|
|
|
|
|
String func = functions[random.nextInt(functions.length)];
|
|
|
|
|
int angle = random.nextInt(100);
|
|
|
|
|
int angle;
|
|
|
|
|
if ("tan".equals(func)) {
|
|
|
|
|
angle = random.nextInt(90); // tan的角度范围 0-89
|
|
|
|
|
} else {
|
|
|
|
|
angle = random.nextInt(361); // sin/cos的角度范围 0-360
|
|
|
|
|
}
|
|
|
|
|
expr.append(func).append("(").append(angle).append(")");
|
|
|
|
|
hasTrig = true;
|
|
|
|
|
} else {
|
|
|
|
|
expr.append(random.nextInt(100) + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasTrig) {
|
|
|
|
|
String func = functions[random.nextInt(functions.length)];
|
|
|
|
|
int angle = random.nextInt(100);
|
|
|
|
|
char op = operators[random.nextInt(operators.length)];
|
|
|
|
|
expr.append(" ").append(op).append(" ");
|
|
|
|
|
expr.append(func).append("(").append(angle).append(")");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return expr.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -224,15 +287,17 @@ public class QuestionGenerator {
|
|
|
|
|
* @return 计算结果
|
|
|
|
|
*/
|
|
|
|
|
private double evaluateExpression(String expression) {
|
|
|
|
|
String expr = expression.replace(" ", "");
|
|
|
|
|
|
|
|
|
|
expr = expr.replaceAll("pow\\((\\d+),2\\)", "($1*$1)");
|
|
|
|
|
expr = expr.replaceAll("sqrt\\((\\d+)\\)", "Math.sqrt($1)");
|
|
|
|
|
expr = expr.replaceAll("sin\\((\\d+)\\)", "Math.sin(Math.toRadians($1))");
|
|
|
|
|
expr = expr.replaceAll("cos\\((\\d+)\\)", "Math.cos(Math.toRadians($1))");
|
|
|
|
|
expr = expr.replaceAll("tan\\((\\d+)\\)", "Math.tan(Math.toRadians($1))");
|
|
|
|
|
|
|
|
|
|
return eval(expr);
|
|
|
|
|
// 预处理表达式,将自定义格式转换为标准格式
|
|
|
|
|
String processedExpression = expression.replaceAll("√(\\d+)", "sqrt($1)");
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
return eval(processedExpression);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("表达式求值失败: " + expression);
|
|
|
|
|
System.err.println("处理后: " + processedExpression);
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
throw new IllegalArgumentException("无效的表达式: " + expression, e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|