• java实现小学生四则运算


    GitHub地址https://github.com/TaoTaoLv1/arithmetic

    结对伙伴:叶文涛

    项目要求:

    实现一个自动生成小学四则运算题目的命令行程序.

    • 使用 -n 参数控制生成题目的个数(完成)
    • 使用 -r 参数控制题目中数值的范围, 。该参数可以设置为1或其他自然数。(完成)
    • 生成的题目中计算过程不能产生负数(完成)
    • 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。(完成)
    • 程序一次运行生成的题目不能重复,生成的题目存入执行程序的当前目录下的Exercises.txt文件(完成)
    • 每道题目中出现的运算符个数不超过3个(完成)
    • 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件(完成)
    • 程序应能支持一万道题目的生成。(完成)
    • 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计。(完成)

    设计:

    分为两个部分,第一是生成题目,生成表达式及答案后写入当前目录下的文件,第二是判断答案是否正确,读取文件后判断,再将结果写入当前目录下的文件。

     代码

     主函数

     public static void main(String[] args){
    
                System.out.println("请选择功能:");
                System.out.println("    1. 四则运算生成器");
                System.out.println("    2. 答案对比");
                System.out.print("请输入你的选择[1/2]:");
                int choose = new Scanner(System.in).nextInt();
    
                switch (choose){
                    case 1:
                        ProducerController producerController = new ProducerController();
                        producerController.ConstructProblem();break;
                    case 2:
                        JudgeAnswerController judgeAnswerController = new JudgeAnswerController();
                        judgeAnswerController.start();break;
                    default:
                        System.out.println("输入不正确,请输入1或2");main(args);break;
                }
        }

    整数生成器与真分数生成器函数

     public String[] createProblem(int range){
                Random random = new Random();
                int operatorCount = 1 + random.nextInt(3); //随机操作符的个数(1-3个)
                int operand[] = new int[operatorCount + 1]; //操作数个数
                int[] operatorIndex = index(operatorCount, 4, random);
    
                for(int i = 0; i < operatorCount + 1; i++){
                    operand[i] = random.nextInt(range);
                }
    
                String formula = stitchingFormula(operatorCount, operand, operatorIndex);
    
                //计算结果
                Calculator calculator = new Calculator();
                int res = calculator.algorithm(formula);
                String formulaRes[] = new String[2];
    
                if (res > 0){
                    formulaRes[0] = formula;
                    formulaRes[1] = String.valueOf(res);
                }else {
                    return createProblem(range);
                }
                return formulaRes;
            }
     public String[] createProblem(int range){
                Random random = new Random();
                int operatorCount = 1 + random.nextInt(3); //操作符的个数1-3
    
                CreateInteger create = new CreateInteger();
                int[] operatorIndex = create.index(operatorCount,2, random); //操作符的下标
    
                //生成第一个操作数
                int[] coprimeNumber1 = createCoprimeNumbers(range, random);
                int x = coprimeNumber1[0];
                int y = coprimeNumber1[1];
    
                String s = shamToProperFraction(x, y);
    
                for(int i=0; i < operatorCount; i++){
                    //生成剩下的操作数
                    int[] coprimeNumber = createCoprimeNumbers(range, random);
                    int numx = coprimeNumber[0];
                    int numy = coprimeNumber[1];
    
                    String currentOpreator = OPERATOR[operatorIndex[i]];
    
                    if(currentOpreator.equals("+")){  //加法
                        x = x * numy + y * numx;
                        y = y * numy;
                    }else {   //减法
                        int count = 0;
                        while(x * numy - y * numx < 0){ //差为负数
                            coprimeNumber = createCoprimeNumbers(range, random);
                            numx = coprimeNumber[0];
                            numy = coprimeNumber[1];
                            count++;
                            if (count >= 5){
                                numx = x - 1;
                                numy = y;
                            }
                        }
                        x = x * numy - y * numx;
                        y = y * numy;
                    }
    
                    String num = shamToProperFraction(numx, numy);
                    s += currentOpreator + num;
                }
    
                int greatFactor = greatFactor(x,y);
                x /= greatFactor; //最终结果化简
                y /= greatFactor;
    
                String res = shamToProperFraction(x, y);
                s += "=";
    
                String formulaRes[] = {s, res};
                return formulaRes;
            }
    
     /**
             * 假分数转化为真分数
             * @param x 分子
             * @param y 分母
             * @return
             */
            public String shamToProperFraction(int x, int y){
                if (x > y){
                    int n = x / y;
                    x = (x - n * y);
                    if (x == 0){
                        return String.valueOf(n);
                    }
                    return n + "'" + x + "/" + y;
                }else if (x == y){
                    return "1";
                }else if (y == 1){
                    return String.valueOf(x);
                }else if (x == 0){
                    return "0";
                }
                return x + "/" + y;
        }
    }

    计算结果函数

        public int algorithm(String s) {
            Stack<Integer> numStack = new Stack<>(); //放数字
            Stack<String> operatorStack = new Stack<>(); //放操作符
            HashMap<String, Integer> hashMap = new HashMap<>(); //存放运算符优先级
            hashMap.put("(", 0);
            hashMap.put("+", 1);
            hashMap.put("-", 1);
            hashMap.put("*", 2);
            hashMap.put("÷", 2);
    
            String formula = s.replaceAll(" ", "");
    
            for (int i = 0; i < formula.length();) {
                StringBuilder digit = new StringBuilder();  //StringBuilder类中的方法主要偏重于对于字符串的变化,例如追加、插入和删除等,这个也是StringBuffer和String类的主要区别。
                char c = formula.charAt(i); //将式子字符串切割为c字符
                while (Character.isDigit(c)) { //判断字符是否为10进制数字,将一个数加入digit
                    digit.append(c);
                    i++;
                    if (i < formula.length()){
                        c = formula.charAt(i);
                    }else {
                        break;
                    }
                }
                if (digit.length() == 0){ //当前digit里面已经无数字,即当前处理符号
                    switch (c) {
                        case '(': {
                            operatorStack.push(String.valueOf(c));//如果是(   转化为字符串压入字符栈
                            break;
                        }
                        case ')': { //遇到右括号了计算,因为(的优先级最高
                            String stmp = operatorStack.pop(); //如果是),将符号栈栈顶元素取到
                            while (!operatorStack.isEmpty() && !stmp.equals("(")) { //当前符号栈里面还有+ - * /
                                int a = numStack.pop();  //取操作数a,b
                                int b = numStack.pop();
                                int result = calculate(b, a, stmp); //计算
                                if(result < 0)
                                    return  -1;
                                numStack.push(result); //将结果压入栈
                                stmp = operatorStack.pop(); //符号指向下一个计算符号
                            }
                            break;
                        }
                        case '=': { //遇到等号了计算
                            String stmp;
                            while (!operatorStack.isEmpty()) { //当前符号栈里面还有+ - * /,即还没有算完
                                stmp = operatorStack.pop();
                                int a = numStack.pop();
                                int b = numStack.pop();
                                int result = calculate(b, a, stmp);
                                if(result < 0)
                                    return  -1;
                                numStack.push(result);
                            }
                            break;
                        }
                        default: {  //不满足之前的任何情况
                            String stmp;
                            while (!operatorStack.isEmpty()) { //如果符号栈有符号
                                stmp = operatorStack.pop(); //当前符号栈,栈顶元素
                                if (hashMap.get(stmp) >= hashMap.get(String.valueOf(c))) { //比较优先级
                                    int a = numStack.pop();
                                    int b = numStack.pop();
                                    int result =calculate (b, a, stmp);
                                    if(result < 0)
                                        return  -1;
                                    numStack.push(result);
                                }
                                else {
                                    operatorStack.push(stmp);
                                    break;
                                }
    
                            }
                            operatorStack.push(String.valueOf(c));  //将符号压入符号栈
                            break;
                        }
                    }
                }
                else { //处理数字,直接压栈
                    numStack.push(Integer.valueOf(digit.toString()));  //Integer.valueof()返回的是Integer对象,而Integer.parseInt()返回的是int型
                    continue; //结束本次循环,回到for语句进行下一次循环,即不执行i++(因为此时i已经指向符号了)
                }
                i++;
            }
            return numStack.peek();  //返回栈底数字即等式的答案。
        }

    判断结果函数

     public void start(){
            System.out.print("请输入待验证答案路径:");
            Scanner scanner = new Scanner(System.in);
            String exerciseFilePath = scanner.next();
            System.out.print("请输入程序生成答案文件路径:");
            String answerFilePath = scanner.next();
    
            try {
                List<String> exerciseAnswers = exerciseFileReader(exerciseFilePath);
                List<String> answers = answerReader(answerFilePath);
    
                List<String> correct = new ArrayList<>();
                List<String> wrong = new ArrayList<>();
    
                int max = Math.max(exerciseAnswers.size(), answers.size());
                int num = 1;
                for (int i = 0; i < max; i++){
                    if (exerciseAnswers.get(i).equals(answers.get(i))){
                        correct.add(String.valueOf(num++));
                    }else {
                        wrong.add(String.valueOf(num++));
                    }
                }
    
                File grade = new File("Grade.txt");
                if (grade.exists()){
                    grade.delete();
                }
                if (grade.createNewFile()){
                    FileOutputStream gradeOutput = new FileOutputStream(grade);
                    PrintStream gradePrintStream = new PrintStream(gradeOutput);
                    String corrects = String.join(",", correct);
                    gradePrintStream.println("Correct:" + correct.size() +
                            " (" + corrects + ")");
                    String wrongs = String.join(",", wrong);
                    gradePrintStream.println("Wrong:" + wrong.size() +
                            " (" + wrongs + ")");
                }
    
                System.out.println("判定完成");
    
            } catch (FileNotFoundException e) {
                System.out.println("文件不存在");
            } catch (IOException e) {
                System.out.println("文件读入异常");
            }
        }
    
        public List<String> exerciseFileReader(String path) throws IOException {
            BufferedReader exerciseReader = new BufferedReader(new FileReader(path));
            String exerciseAnswer = "";
            List<String> exerciseAnswers = new ArrayList<>();
            while ((exerciseAnswer = exerciseReader.readLine()) != null){
                String[] split = exerciseAnswer.split("=");
                if (split[1] != null){
                    exerciseAnswers.add(split[1]);
                }else {
                    exerciseAnswers.add(" ");
                }
            }
            return exerciseAnswers;
        }

    测试

    1.随机生成10道10以内的四则运算

     2.判断题目的正确与否

    3.支持生成一万道题目

    由于题目过多,因此直接在连接中打开

    测试题目文件

    测试答案文件

    以上就是所有功能的测试

    PSP表格

    PSP2.1

    Personal Software Process Stages

    预估耗时(分钟)

    实际耗时(分钟)

    Planning

    计划

    10

    5

    · Estimate

    · 估计这个任务需要多少时间

    800

    1200

    Development

    开发

    480

    630

    · Analysis

    · 需求分析 (包括学习新技术)

    60

    30

    · Design Spec

    · 生成设计文档

    60

    80

    · Design Review

    · 设计复审 (和同事审核设计文档)

    30

    45

    · Coding Standard

    · 代码规范 (为目前的开发制定合适的规范)

    30

    30

    · Design

    · 具体设计

    30

    60

    · Coding

    · 具体编码

    120

    360

    · Code Review

    · 代码复审

    30

    45

    · Test

    · 测试(自我测试,修改代码,提交修改)

    120

    120

    Reporting

    报告

    120

    120

    · Test Report

    · 测试报告

    60

    30

    · Size Measurement

    · 计算工作量

    30

    30

    · Postmortem & Process Improvement Plan

    · 事后总结, 并提出过程改进计划

    30

    30

    合计

     

    1200

    1610

    总结

    在这次编程作业中,我和叶文涛同学一起讨论,他主要负责编写代码,后期的测试和报告则由我负责,在这一次的作业中,我也从伙伴身上学习到了很多,认识到自己与他人之间的差距,他在编程过程中也耐心的解答我的疑惑,在这个过程中不断的完善代码。两个人一起处理问题,互相汲取对方好的想法,有些细节没有考虑到的,另一个人可以帮忙补充,这样使得效率也大大提高。例如在我们进行最后测试的过程中,我发现当计算答案时如果答案为空则会出错,在这个情况下我们进行讨论之后也克服了这个问题。

  • 相关阅读:
    在unity中内置一个查询物流信息功能
    socket 广播消息
    Socket通信
    用SecureCRT在windows和CentOS间上传下载文件
    Centos6.5下设置静态IP
    oracle 11g dataguard创建的简单方法
    linux下mysql安装、目录结构、配置
    dba诊断之lock
    oracle11G在linux环境下的卸载操作
    Ubuntu 14.04(32位)安装Oracle 11g(32位)全过程
  • 原文地址:https://www.cnblogs.com/chenjiaman/p/9688368.html
Copyright © 2020-2023  润新知