Student.java package com.az.test.calc; import java.util.Scanner; import com.az.test.calc.CreateShiZi; import com.az.test.calc.NiBoLanShi; public class Student { public static void main(String[] args) { CreateShiZi createShiZi = new CreateShiZi(); NiBoLanShi niBoLanShi = new NiBoLanShi(); String[] fuHao = {"+","-","*","/"}; Scanner input = new Scanner(System.in); System.out.println("请输入范围内的计算:"); int m = input.nextInt(); System.out.println("请输入要产生的题数:"); int n = input.nextInt(); String[] strArray = new String[n]; System.out.println("\n题目\n"); createShiZi.create(m, n, fuHao, strArray); for(int i = 0; i<n; i++) { String result = niBoLanShi.cal(strArray[i]); System.out.println("第"+(i+1)+"题:"+strArray[i]); System.out.print("你的答案:"); String yourAnswer = input.next(); if (yourAnswer.equals(result)) { System.out.println("True\n"); }else { System.out.println("False"); System.out.println("正确答案:"+result+"\n"); } } } } NiBoLanShi.java package com.az.test.calc; import java.util.List; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Stack; public class NiBoLanShi { public static String cal(String str) { //对表达式进行预处理,并简单验证是否是正确的表达式 //存放处理后的表达式 List<String> list = new ArrayList<>(); char[] arr = str.toCharArray(); //存放数字临时变量 StringBuffer tmpStr = new StringBuffer(); for (char c : arr) { //如果是数字或小数点,添加到临时变量中 if (c>='0' && c<='9') { tmpStr.append(c); }else if(c=='.') { if(tmpStr.indexOf(".")>0) { throw new RuntimeException("非法字符"); } tmpStr.append(c); } //如果是加减乘除或者括号,将数字临时变量和运算符依次放入List中 else if (c=='+' || c=='-' || c=='*' || c=='/' || c=='(' || c==')') { if (tmpStr.length() > 0) { list.add(tmpStr.toString()); tmpStr.setLength(0); } list.add(c + ""); } else if (c==' ') { continue; } else { throw new RuntimeException("非法字符"); } } if (tmpStr.length() > 0) { list.add(tmpStr.toString()); } //初始化后缀表达式 List<String> strList = new ArrayList<>(); //运算过程中,使用了两次栈结构, //第一次是将中缀表达式转换成后缀表达式,第二次是计算后缀表达式的值 Stack<String> stack = new Stack<>(); //声明临时变量,存放栈元素 String tmp; //将中缀表达式转换成后缀表达式 for (String s : list) { //如果是左括号直接入栈 if (s.equals("(")) { stack.push(s); } //如果是右括号,执行出栈操作,依次添加到后缀表达式中,直到出栈元素为左括号,左括号和右括号都不添加到后缀表达式中 else if (s.equals(")")) { while (!(tmp = stack.pop()).equals("(")) { strList.add(tmp); } } //如果是加减乘除,弹出所遇优先级大于或等于该运算符的栈顶元素(栈中肯定没有右括号,认为左括号的优先级最低),然后将该运算符入栈 else if (s.equals("*") || s.equals("/")) { while(!stack.isEmpty()) { //取出栈顶元素 tmp = stack.peek();//取出但不移除 if (tmp.equals("*") || tmp.equals("/")) { stack.pop(); strList.add(tmp); } else { break; } } stack.push(s); } else if (s.equals("+") || s.equals("-")) { while(!stack.isEmpty()) { //取出栈顶元素 tmp = stack.peek(); if (!tmp.equals("(")) { stack.pop(); strList.add(tmp); } else { break; } } stack.push(s); } //如果是数字,直接添加到后缀表达式中 else { strList.add(s); } } //最后依次出栈,放入后缀表达式中 while (!stack.isEmpty()) { strList.add(stack.pop()); } //计算后缀表达式的值 Stack<BigDecimal> newStack = new Stack<>(); for (String s : strList) { //若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符的左边 //运算后的结果再进栈,直到后缀表达式遍历完毕 if (s.equals("*") || s.equals("/") || s.equals("+") || s.equals("-")) { BigDecimal b1 = newStack.pop(); BigDecimal b2 = newStack.pop(); switch (s) { case "+": newStack.push(b2.add(b1)); break; case "-": newStack.push(b2.subtract(b1)); break; case "*": newStack.push(b2.multiply(b1)); break; case "/": newStack.push(b2.divide(b1, 9, BigDecimal.ROUND_HALF_UP)); break; } } //如果是数字,入栈 else { newStack.push(new BigDecimal(s)); } } //最后,栈中仅有一个元素,就是计算结果 return newStack.peek().toString(); } } CreateShiZi.java package com.az.test.calc; public class CreateShiZi { public void create(int m, int n, String[] fuHao, String[] strArray) { String str = ""; //随机生成式子 for (int i = 0; i < n; i++) { str = ""; int[] arr1 = new int[n]; int[] arr2 = new int[n]; arr2[i] = (int)(Math.random()*m+1); for(int j = 0; j < (int)(Math.random()*10+1); j++) { int order = (int)(Math.random()*4); arr1[j] = (int)(Math.random()*m+1); str = str + arr1[j] + fuHao[order]; } str = str + arr2[i]; strArray[i] = str; System.out.println("第"+(i+1)+"题:"+str); arr1 = null; arr2 = null; } System.out.println("\n"); } }