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.
Math_Learning/src/Base/Question.java

268 lines
10 KiB

package Base;
import java.util.HashMap;
import java.util.Random;
import java.util.Stack;
public class Question {
private int number;
private String content;
private String type;
private String answer;
private String[] options;
private final Random ra= new Random();
public static final HashMap<String, String> trigValues = new HashMap<>();
static {
// 15°
trigValues.put("sin(15°)", "√2*(√3-1)/4");
trigValues.put("cos(15°)", "√2*(√3+1)/4");
trigValues.put("tan(15°)", "(2-√3)");
trigValues.put("sin²(15°)", "(2-√3)/4");
trigValues.put("cos²(15°)", "(2+√3)/4");
trigValues.put("tan²(15°)", "(7-4*√3)");
// 22.5°
trigValues.put("sin(22.5°)", "√0.59/2"); //√(2-√2)/2
trigValues.put("cos(22.5°)", "√3.41/2"); //√(2+√2)/2
trigValues.put("tan(22.5°)", "(√2-1)");
trigValues.put("sin²(22.5°)", "(2-√2)/4");
trigValues.put("cos²(22.5°)", "(2+√2)/4");
trigValues.put("tan²(22.5°)", "(3-2*√2)");
// 75°
trigValues.put("sin(75°)", "√2*(√3+1)/4");
trigValues.put("cos(75°)", "√2*(√3-1)/4");
trigValues.put("tan(75°)", "(2+√3)");
trigValues.put("sin²(75°)", "(2+√3)/4");
trigValues.put("cos²(75°)", "(2-√3)/4");
trigValues.put("tan²(75°)", "(7+4*√3)");
// 105°
trigValues.put("sin(105°)", "√2*(√3+1)/4");
trigValues.put("cos(105°)", "√2*(1-√3)/4");
trigValues.put("tan(105°)", "(0-(2+√3))");
trigValues.put("sin²(105°)", "(2+√3)/4");
trigValues.put("cos²(105°)", "(2-√3)/4");
trigValues.put("tan²(105°)", "(7+4*√3)");
// 120°
trigValues.put("sin(120°)", "√3/2");
trigValues.put("cos(120°)", "(0-1/2)");
trigValues.put("tan(120°)", "(0-√3)");
trigValues.put("sin²(120°)", "3/4");
trigValues.put("cos²(120°)", "1/4");
trigValues.put("tan²(120°)", "3");
// 135°
trigValues.put("sin(135°)", "√2/2");
trigValues.put("cos(135°)", "(0-√2/2)");
trigValues.put("tan(135°)", "(0-1)");
trigValues.put("sin²(135°)", "1/2");
trigValues.put("cos²(135°)", "1/2");
trigValues.put("tan²(135°)", "1");
// 150°
trigValues.put("sin(150°)", "1/2");
trigValues.put("cos(150°)", "(0-√3/2)");
trigValues.put("tan(150°)", "(0-√3/3)");
trigValues.put("sin²(150°)", "1/4");
trigValues.put("cos²(150°)", "3/4");
trigValues.put("tan²(150°)", "1/3");
// 210°
trigValues.put("sin(210°)", "(0-1/2)");
trigValues.put("cos(210°)", "(0-√3/2)");
trigValues.put("tan(210°)", "√3/3");
trigValues.put("sin²(210°)", "1/4");
trigValues.put("cos²(210°)", "3/4");
trigValues.put("tan²(210°)", "1/3");
// 300°
trigValues.put("sin(300°)", "(0-√3/2)");
trigValues.put("cos(300°)", "1/2");
trigValues.put("tan(300°)", "(0-√3)");
trigValues.put("sin²(300°)", "3/4");
trigValues.put("cos²(300°)", "1/4");
trigValues.put("tan²(300°)", "3");
}
public Question(int number, String content, String type) {
this.number = number;
this.content = content;
this.type = type;
options=new String[4];
}
public int getNumber() { return number; }
public String getContent() { return content; }
public String getType() { return type; }
public String getAnswer() {return answer;}
public String getOptions(int i) {return options[i];}
@Override
public String toString(){
return this.number+". "+this.content+" = ?";
}
public void set_options(){
answer=calculate(this.content);
int which=ra.nextInt(4);
options[which]=answer;
for (int i=0;i<4;i++) {
if (i != which) {
if (this.type.equals("高中")) {
options[i] = answer.equals("不可解") ? String.format("%.2f", Math.sqrt(3) * ra.nextInt(10) + ra.nextDouble(1)) :
String.format("%.2f", Double.parseDouble(answer) + Math.sqrt(2) * ra.nextInt(5));
} else {
if (Double.parseDouble(answer) ==Math.floor(Double.parseDouble(answer)) ) {
options[i] = answer.equals("不可解") ? String.valueOf((int) ra.nextInt(1000) + ra.nextInt(10)) :
String.valueOf((int) Double.parseDouble(answer) + ra.nextInt(10));
} else {
options[i] = answer.equals("不可解") ? String.format("%.2f", ra.nextInt(1000) + ra.nextDouble(10)) :
String.format("%.2f", Double.parseDouble(answer) + ra.nextDouble(10));
}
}
for (int j = 0; j < i; j++) {
if (options[j].equals(options[i])) {
i--;
break;
}
}
if (options[i].equals(answer)) {
i--;
}
}
}
}
public String calculate(String question){
try {
String expr = question.replaceAll(" ", "");
double result;
if (!type.equals("高中")) {
result = deal_calculate(expr);
if (Double.isNaN(result) || Double.isInfinite(result)) {
return "不可解";
}
if (result == Math.floor(result)) {
return String.valueOf((int) result);
} else {
return String.format("%.2f", result);
}
}
else{
return deal_sen_calculate(expr);
}
} catch (Exception e) {
return "不可解";
}
}
private double deal_calculate(String expr){
Stack<Double> numbers = new Stack<>();
Stack<Character> operators = new Stack<>();
expr=expr.replace("²", "^2");
for (int i = 0; i < expr.length(); i++) {
char c = expr.charAt(i);
if (Character.isDigit(c)) {
StringBuilder temp = new StringBuilder();
while (i < expr.length() && (Character.isDigit(expr.charAt(i)) || expr.charAt(i) == '.')) {
temp.append(expr.charAt(i++));
}
i--;
numbers.push(Double.parseDouble(temp.toString()));
} else if (c == '(') {
operators.push(c);
} else if (c == ')') {
while (operators.peek() != '(') {
numbers.push(Deal_Operator(operators.pop(), numbers.pop(), numbers.pop()));
}
operators.pop();
} else if (isOperator(c)) {
while (!operators.isEmpty() && hasPrecedence(c, operators.peek())) {
numbers.push(Deal_Operator(operators.pop(), numbers.pop(), numbers.pop()));
}
operators.push(c);
}
else if (c == '√'){
i++;
StringBuilder temp = new StringBuilder();
while (i < expr.length() && (Character.isDigit(expr.charAt(i)) || expr.charAt(i) == '.')) {
temp.append(expr.charAt(i++));
}
i--;
numbers.push(Math.sqrt(Double.parseDouble(temp.toString())));
}
}
while (!operators.isEmpty()) {
numbers.push(Deal_Operator(operators.pop(), numbers.pop(), numbers.pop()));
}
return numbers.pop();
}
private String deal_sen_calculate(String m_expr){
try {
String expr = m_expr.replaceAll(" ", "");
StringBuilder result = new StringBuilder();
int i = 0;
while (i < expr.length()) {
char c = expr.charAt(i);
if (c == 's' || c == 'c' || c == 't') {
StringBuilder trigFunc = new StringBuilder();
while (i < expr.length() && expr.charAt(i) != ')') {
trigFunc.append(expr.charAt(i++));
}
trigFunc.append(')'); // 添加右括号
String trigKey = trigFunc.toString();
String trigValue = trigValues.get(trigKey);
if (trigValue != null) {
result.append(trigValue);
}
} else if (isOperator(c) || c == '(' || c == ')') {
result.append(c);
}
i++;
}
return String.format("%.2f",deal_calculate(Deal_Expression(result.toString())));
} catch (Exception e) {
return "不可解";
}
}
private double Deal_Operator(char operator, double b, double a) {
switch (operator) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': {
if (b == 0) throw new ArithmeticException("除零错误");
return a / b;
}
case '^': return Math.pow(a, b);
default: return 0;
}
}
private boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
}
//检验运算优先级,来决定先计算再压栈还是直接压栈
private boolean hasPrecedence(char op1, char op2) {
if ( (op2 == '(' || op2 == ')')
|| ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
|| (op1 == '^' && (op2 == '*' || op2 == '/' || op2 == '+' || op2 == '-'))) {
return false;
}
return true;
}
private String Deal_Expression(String expr) {
String simplified = expr.replace("+-","-");
simplified = simplified.replace("--","+");
return simplified;
}
}