自动生成小学四则运算题目
题目
思路分析(题目分解)
1.输入数字自动生成四则运算的题目
①确定算式长度生成一个随机数(5-9) n
②循环n次
出现能被2整除的数字则自动生成一个1-9以内的数字
出现不能被2整除的数字则自动生成+-*/运算符(将来拓展()的加入)
在除法时应该考虑不出现小数,所以要确定后面的数可以将前面生成的那个数整除
③判断当前算式的答案是否为复数,或者大于100 如果不满足前面的条件则将算式存入到list集合中,否则将循环数减1,重新循环。
2.求解四则运算的题目(考虑到堆栈和后缀表达式)
①生成两个堆栈,分别用来存储数字和运算符
②利用正则表达式将运算式进行拆解
③对各个分解后的结果进行遍历,如果是运算数就存入到运算数的栈中,如果是运算符就要进行优先级的判断,如果栈定的优先级如果大于当前这个要存入的运算符的话,就取出这个运算符和运算数中的后两个数字进行计算(注意:以为栈是先进后出,如果取出来的是/,那么后取出来的的数是被除数!)。如果出现”)“,则一直取出运算符栈和运算数栈中的内容,知道运算符栈取出的是”(“为止;
④遍历结束,将运算栈中的内容清空,返回结果值
代码展示
主函数:
public static void main(String[] args) throws Exception {
System.out.println("请输入要生成的练习题数量:");
Scanner scanner = new Scanner(System.in);
Integer testCount = scanner.nextInt();
List<String> tests= generateTest(testCount);
int score=0;
for (int i=0;i<tests.size();i++){
System.out.println(tests.get(i));
System.out.println("请输入您的答案:");
if (getResult(tests.get(i))==scanner.nextDouble()){
System.out.println("答案正确!");
score++;
}else{
System.out.println("答案错误!");
}
}
System.out.println("您的成绩为:"+score*100/testCount);
}
生成题目函数
public static List<String> generateTest(int num) throws Exception {
List<String> listTest =new ArrayList<>();
for(int i=0;i<num;i++){
StringBuffer sb=new StringBuffer();
int lenth=rd.nextInt(3)+6;//生成一个5--9长度的算术题
for (int j=0;j<lenth;j++){
if (j%2==0) {
sb.append(rd.nextInt(9) + 1);//生成一个1-9的随机数
}else{
switch (rd.nextInt(4)){
case 0:sb.append("+");break;
case 1:sb.append("-");break;
case 2:sb.append("*");break;
case 3:
//必须生成整数
while (true){
int t=rd.nextInt(9)+1;
if ( sb.charAt(sb.length() - 1)%t==0){
sb.append("/"+t);
j++;
break;
}
};break;
}
}
}
if((String.valueOf(sb.charAt(sb.length()-1))).matches("[+\\-*/]")) {
sb.append((rd.nextInt(9) + 1));
}
if (getResult(sb.toString())<0||(rd.nextInt(9) + 1)>100){
i--;
continue;
}
listTest.add(sb.toString());
}
return listTest;
}
计算结果
/**
* 用于计算加减法 可以直接调用
* @param a1
* @param a2
* @param operator
* @return
* @throws Exception
*/
private static double doubleCal(double a1, double a2, char operator) throws Exception {
switch (operator) {
case '+':
return a1 + a2;
case '-':
return a1 - a2;
case '*':
return a1 * a2;
case '/':
return a1 / a2;
default:
break;
}
throw new Exception("illegal operator!");
}
/**
* 优先级的运算 判断出栈入栈
* @param s
* @return
* @throws Exception
*/
private static int getPriority(String s) throws Exception {
if (s==null){
return 0;
}else if(s.equals("(")){
return 1;
}else if (s.equals("*")|| s.equals("/")){
return 3;
}else if(s.equals("+") ||s.equals("-")){
return 2;
}else{
throw new Exception("非法操作!");
}
}
/**
* 获取结果
* @param s
* @return
* @throws Exception
*/
public static double getResult(String s) throws Exception {
Stack<Double> Number=new Stack<>();
Stack<String> Operator=new Stack<>();
Operator.add(null);
Pattern p= compile("\\d|[+\\-*/()]");
Matcher m=p.matcher(s);
while (m.find()){
String temp=m.group();
if (temp.equals("(")){//直接进入运算符栈
Operator.add(temp);
}else if (temp.equals(")")){
String b=null;
while (!(b=Operator.pop()).equals("(")){//直到出现)才截止
double number2=Number.pop();
double number1=Number.pop();
double res= doubleCal(number1,number2,b.charAt(0));
Number.add(res);
}
}else if (temp.matches("[+\\-*/]")){//判断是否为运算符
if (Operator.peek()==null){//如果运算符中没有运算符则直接加入运算符栈
Operator.add(temp);
continue;
}
while (getPriority(temp)<=getPriority(Operator.peek())){//如果当前要入栈的运算优先级低于栈顶运算符的栈 那么就取出进行计算
double number2=Number.pop();
double number1=Number.pop();
String op=Operator.pop();
Number.add(doubleCal(number1,number2,op.charAt(0))) ;
}
Operator.add(temp);
}else{
Number.add(Double.parseDouble(temp));//运算数直接进入运算数栈
}
}
while(Operator.peek()!=null){//循环结束 将运算栈中的内容清空
double number2=Number.pop();
double number1=Number.pop();
Number.add(doubleCal(number1,number2,Operator.pop().charAt(0)));
}
return Number.pop();
}