• 四则运算 Java 杨辉鹏,郑冠华


    四则运算 Java 杨辉,郑冠华


    GitHub链接:https://github.com/yanghuipeng/arithmetic

     

    项目相关要求

    1. 使用 -n 参数控制生成题目的个数,例如

         -n 10 将生成10个题目。

    1. 使用 -r 参数控制题目中数值(自然数、真分数)的范围,例如

         -r 10

        将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。

    1. 生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1 − e2的子表达式,那么e1 ≥ e2。

    2. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。

    3. 每道题目中出现的运算符个数不超过3个。

    4. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。

        生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:

      1. 四则运算题目1

      2. 四则运算题目2

        其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。

    1. 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:

      1.答案1

      2.答案2

        特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。

    1. 程序应能支持一万道题目的生成。

    2. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:

        Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt

        统计结果输出到文件Grade.txt,格式如下:

          Correct: 5 (1, 3, 5, 7, 9)

          Wrong: 5 (2, 4, 6, 8, 10)

        其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。

    PSP开发耗时

    PSP2.1

    PSP2.1

    Personal Software Process Stages

    预估耗时(分钟)

    实际耗时(分钟)

    Planning

    计划

     30  50

    · Estimate

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

     30  50

    Development

    开发

     1100  2260

    · Analysis

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

     80  180

    · Design Spec

    · 生成设计文档

     60  100

    · Design Review

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

     30  40

    · Coding Standard

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

     30  30

    · Design

    · 具体设计

     100  150

    · Coding

    · 具体编码

     600  1500

    · Code Review

    · 代码复审

     50  60

    · Test

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

     150  200

    Reporting

    报告

     80  80

    · Test Report

    · 测试报告

     30  40

    · Size Measurement

    · 计算工作量

     20  20

    · Postmortem & Process Improvement Plan

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

     30  20

    合计

       1210  2390

    解题思路:

    • 生成随机操作数

    • 取随机操作符

    • 生成表达式

    • 计算
    • 判重

    • 结果写入文件

    设计实现过程

    • Fraction分数类定义一个分数及分数的基本操作

    • Expression表达式类定义一个表达式及计算表达式的结果
    • Function输出功能类输出结果

    代码

    项目目录:

    主函数:(启动程序)Main.java

    package TwoProject;
    
    import java.io.*;
    import java.util.Scanner;
    
    public class Main {
    
        public static void main(String[] args) throws IOException {
            // TODO 自动生成的方法存根
            int titleNum; // 定义题目个数
            int parameterRange; // 定义参数范围
            System.out.println("**** -n [数值]     使用 -n 参数控制生成题目的个数");
            System.out.println("**** -e <exercisefile>.txt -a <answerfile>.txt  对给定的题目文件和答案文件,判定答案中的对错并进行数量统计");
            System.out.print("请输入命令:");
            Scanner s = new Scanner(System.in);
            String m = s.nextLine();
            String str[] = m.split("\s");
            switch (str[0]) {
            case "-n":
                titleNum = Integer.valueOf(str[1].toString());
                System.out.println("**** -r [数值]     使用 -r 参数控制题目中数值(自然数、真分数)的范围(数值应大于1)");
                System.out.print("请输入命令:");
                Scanner ss = new Scanner(System.in);
                String n = ss.nextLine();
                String strr[] = n.split("\s");
                if (strr[0].equals("-r")) {
                    parameterRange = Integer.valueOf(strr[1].toString());
                    Function function = new Function(titleNum, parameterRange);
                    function.outputExercises();
                    break;
                } else {
                    System.out.println("输入的命令有误!");
                    break;
                }
            case "-e":
                Function function0 = new Function();
                String gradePath = "Grade.txt";
                function0.outputGrade(str[1], str[3], gradePath);
                break;
            default:
                System.out.println("输入的命令有误!");
                break;
            }
            s.close();
    
        }
    
    }

    分数类 Fraction

    package TwoProject;
    
    public class Fraction {
    
        private int a; // 定义分子
        private int b; // 定义分母
    
        public Fraction(String string) { // 将数字的字符串形式转换为整数、分数形式
            string = string.trim(); // 清除前后空格
            int c = string.indexOf("'"); // 求带分数标志“'”的索引
            int d = string.indexOf("/"); // 求分数标志“/”的索引
            if (c != -1) { // 数字为带分数
                int z = Integer.valueOf(string.substring(0, c));
                b = Integer.valueOf(string.substring(d + 1));
                a = z * b + Integer.valueOf(string.substring(c + 1, d));
            } else if (d != -1) { // 数字为真分数
                b = Integer.valueOf(string.substring(d + 1));
                a = Integer.valueOf(string.substring(0, d));
            } else { // 数字为整数
                a = Integer.valueOf(string);
                b = 1;
            }
            build(a, b);
        }
    
        public Fraction(int a, int b) {
            build(a, b);
        }
    
        // 数字形式转换为字符串形式
        public String toString() {
            if (b == 1) {
                return String.valueOf(a);
            } else {
                int i = a / b;
                if (i != 0) {
                    return String.format("%d'%d/%d", i, a - b * i, b);
                } else {
                    return String.format("%d/%d", a, b);
                }
            }
        }
    
        // 给定分子分母构造分数
        private void build(int a, int b) {
            if (b == 0) {
                throw new RuntimeException("分母不能为0");
            }
            int c = comfactor(a, b);
            this.a = a / c;
            this.b = b / c;
        }
    
        // 求公因子
        private int comfactor(int a, int b) {
            int mod = a % b;
            return mod == 0 ? b : comfactor(b, mod);
        }
    
        // 加法 a + b
        public Fraction add(Fraction fraction) {
            return new Fraction(this.a * fraction.b + fraction.a * this.b, this.b * fraction.b);
        }
    
        // 减法 a - b
        public Fraction subtraction(Fraction fraction) {
            return new Fraction(this.a * fraction.b - fraction.a * this.b, this.b * fraction.b);
        }
    
        // 乘法 a x b
        public Fraction multiplication(Fraction fraction) {
            return new Fraction(this.a * fraction.a, this.b * fraction.b);
        }
    
        // 除法a/b
        public Fraction division(Fraction fraction) {
            return new Fraction(this.a * fraction.b, b * fraction.a);
        }
    
        public double getDouble() {
            return a / b;
        }
    }

    表达式类Expression

    package TwoProject;
    
    import java.util.List;
    import java.util.ArrayList;
    import java.util.concurrent.ThreadLocalRandom;
    
    /**
     * 
     * @author 辉鹏
     * @param parameterRange
     *            参数范围
     * 
     * 
     */
    public class Expression {
        int parameterRange;
        char[] symbol = { '+', '-', '×', '÷' };
        boolean isWrong = false;
        String s;
        ThreadLocalRandom random = ThreadLocalRandom.current();
        public Expression(String string) {
            s=string.trim();
            expreGenerate(s);
        }
        public Expression(int parameterRange) {
            super();
            this.parameterRange = parameterRange;
            int n = random.nextInt(1, 4);
            char[] symchar = new char[n];
            char[] symchar1 = new char[n];
            for (int i = 0; i < n; i++) {
                int j = random.nextInt(0, 4);
                symchar[i] = symbol[j];
            }
            for (int i = 0; i < n; i++) {
                if (symchar[i] == '+' || symchar[i] == '-') {
                    symchar1[i] = '1';
                }
                if (symchar[i] == '×' || symchar[i] == '÷') {
                    symchar1[i] = '2';
                }
            }
            String string = symchar1.toString().trim();
            if (n == 1) {
                String[] str0 = new String[4];
                str0[0] = createFraction().toString();
                str0[1] = String.valueOf(symchar[0]);
                str0[2] = createFraction().toString();
                str0[3] = "=";
                StringBuffer stringBuffer = new StringBuffer();
                for (int i = 0; i < 4; i++) {
                    stringBuffer = stringBuffer.append(str0[i] + " ");
                }
                s = stringBuffer.toString();
            } else if (n == 2) {
                if (string == "12" || string == "22") {
                    Object[] str1 = new String[6];
                    str1[0] = createFraction().toString();
                    str1[1] = String.valueOf(symchar[0]);
                    str1[2] = createFraction().toString();
                    str1[3] = String.valueOf(symchar[1]);
                    str1[4] = createFraction().toString();
                    str1[5] = "=";
                    StringBuffer stringBuffer = new StringBuffer();
                    for (int i = 0; i < 6; i++) {
                        stringBuffer = stringBuffer.append(str1[i] + " ");
                    }
                    s = stringBuffer.toString();
                } else {
                    String[] str2 = new String[8];
                    str2[0] = createFraction().toString();
                    str2[1] = String.valueOf(symchar[0]);
                    str2[2] = "(";
                    str2[3] = createFraction().toString();
                    str2[4] = String.valueOf(symchar[1]);
                    str2[5] = createFraction().toString();
                    str2[6] = ")";
                    str2[7] = "=";
                    StringBuffer stringBuffer = new StringBuffer();
                    for (int i = 0; i < 8; i++) {
                        stringBuffer = stringBuffer.append(str2[i] + " ");
                    }
                    s = stringBuffer.toString();
                }
            } else {
                if (string == "221" || string == "222") {
                    String[] str3 = new String[10];
                    str3[0] = createFraction().toString();
                    str3[1] = String.valueOf(symchar[0]);
                    str3[2] = createFraction().toString();
                    str3[3] = String.valueOf(symchar[1]);
                    str3[4] = "(";
                    str3[5] = createFraction().toString();
                    str3[6] = String.valueOf(symchar[2]);
                    str3[7] = createFraction().toString();
                    str3[8] = ")";
                    str3[9] = "=";
                    StringBuffer stringBuffer = new StringBuffer();
                    for (int i = 0; i < 10; i++) {
                        stringBuffer = stringBuffer.append(str3[i] + " ");
                    }
                    s = stringBuffer.toString().trim();
    
                } else if (string == "111" || string == "112") {
                    Object[] str4 = new String[10];
                    str4[0] = createFraction().toString();
                    str4[1] = String.valueOf(symchar[0]);
                    str4[2] = "(";
                    str4[3] = createFraction().toString();
                    str4[4] = String.valueOf(symchar[1]);
                    str4[5] = createFraction().toString();
                    str4[6] = ")";
                    str4[7] = String.valueOf(symchar[2]);
                    str4[8] = createFraction().toString();
                    str4[9] = "=";
                    StringBuffer stringBuffer = new StringBuffer();
                    for (int i = 0; i < 10; i++) {
                        stringBuffer = stringBuffer.append(str4[i] + " ");
                    }
                    s = stringBuffer.toString().trim();
                } else if (string == "121" || string == "122") {
                    Object[] str5 = new String[10];
                    str5[0] = "(";
                    str5[1] = createFraction().toString();
                    str5[2] = String.valueOf(symchar[0]);
                    str5[3] = createFraction().toString();
                    str5[4] = ")";
                    str5[5] = String.valueOf(symchar[1]);
                    str5[6] = createFraction().toString();
                    str5[7] = String.valueOf(symchar[2]);
                    str5[8] = createFraction().toString();
                    str5[9] = "=";
                    StringBuffer stringBuffer = new StringBuffer();
                    for (int i = 0; i < 10; i++) {
                        stringBuffer = stringBuffer.append(str5[i] + " ");
                    }
                    s = stringBuffer.toString().trim();
                } else {
                    Object[] str6 = new String[8];
                    str6[0] = createFraction().toString();
                    str6[1] = String.valueOf(symchar[0]);
                    str6[2] = createFraction().toString();
                    str6[3] = String.valueOf(symchar[1]);
                    str6[4] = createFraction().toString();
                    str6[5] = String.valueOf(symchar[2]);
                    str6[6] = createFraction().toString();
                    str6[7] = "=";
                    StringBuffer stringBuffer = new StringBuffer();
                    for (int i = 0; i < 8; i++) {
                        stringBuffer = stringBuffer.append(str6[i] + " ");
                    }
                    s = stringBuffer.toString().trim();
                }
            }
            expreGenerate(s);
        }
    
        // 随机生成一个分数
        Fraction createFraction() {
            return new Fraction(random.nextInt(1, parameterRange), random.nextInt(1, 10));
        }
    
        // 返回一个表达式
        private String expreGenerate(String s) {
            return s;
        }
    
        // 表达式计算
        private Fraction calculate(String symbol0, Fraction left0, Fraction right0) {
            String symbol = symbol0;
            Fraction left = left0;
            Fraction right = right0;
            switch (symbol) {
            case "+":
                return left.add(right);
            case "-":
                if (left.getDouble() <= right.getDouble()) {
                    isWrong = true;
                    return new Fraction(1, 1);
                } else {
                    return left.subtraction(right);
                }
            case "×":
                return left.multiplication(right);
            default:
                return left.division(right);
            }
        }
    
        // 表达式结果计算方法
        public String getResult() {
            String string = s;
            String[] strings = string.split("\s+");
            List<String> list = new ArrayList<String>();
            for (int i = 0; i < strings.length; i++) {
                list.add(strings[i]);
            }
            if (string.indexOf("(") != -1) {
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(i).equals("="))
                        break;
                    if (list.get(i).equals("(")) {
                        list.set(i, calculate(list.get(i + 2), new Fraction(list.get(i + 1)), new Fraction(list.get(i + 3)))
                                .toString());
                        for (int j = 0; j < 4; j++) {
                            list.remove(i + 1);
                        }
                    }
                }
            }
            if (string.indexOf("×") != -1 || string.indexOf("÷") != -1) {
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(i).equals("="))
                        break;
                    if (list.get(i).equals("×") || list.get(i).equals("÷")) {
                        list.set(i - 1, calculate(list.get(i), new Fraction(list.get(i - 1)), new Fraction(list.get(i + 1)))
                                .toString());
                        for (int j = 0; j < 2; j++) {
                            list.remove(i);
                        }
                        i--;
                    }
                }
            }
            if (string.indexOf("+") != -1 || string.indexOf("-") != -1) {
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(i).equals("="))
                        break;
                    if (list.get(i).equals("+") || list.get(i).equals("-")) {
                        list.set(i - 1, calculate(list.get(i), new Fraction(list.get(i - 1)), new Fraction(list.get(i + 1)))
                                .toString());
                        for (int j = 0; j < 2; j++) {
                            list.remove(i);
                        }
                        i--;
                    }
                }
            }
            return list.get(0);
        }
    
        public String toString() {
            return s;
        }
    }

    输出功能类Function

    package TwoProject;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * @param titleNum
     *            题目个数
     * @param parameterRange
     *            参数范围
     */
    public class Function {
        int titleNum;
        int parameterRange;
        Set<String> set = new HashSet<>();
    
        public Function() {
    
        }
    
        public Function(int titleNum, int parameterRange) {
            this.titleNum = titleNum;
            this.parameterRange = parameterRange;
        }
    
        public void outputExercises() {
            try {
                PrintWriter exercisesWriter = new PrintWriter(new FileWriter("Exercises.txt"));
                PrintWriter answerWriter = new PrintWriter(new FileWriter("Answers.txt"));
                for (int i = 1; i < titleNum + 1;) {
                    Expression expression = new Expression(parameterRange);
                    String string = expression.getResult();
                    if (expression.isWrong == false && !(set.contains(string))) {
                        set.add(string);
                        exercisesWriter.println(i + ". " + expression.toString());
                        answerWriter.println((i + ". " + string));
                        i++;
                    }
                }
                exercisesWriter.close();
                answerWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("已经生成题目和答案");
        }
    
        /**
         * 输出结果
         * 
         * @param exercisePath
         *            表达式文件路径
         * @param answerPath
         *            结果文件路径
         * @param gradePath
         *            输出结果文件路径
         */
        public void outputGrade(String exercisePath, String answerPath, String gradePath) {
    
            try {
                BufferedReader exercisesReader = new BufferedReader(new FileReader(exercisePath));
                BufferedReader answerReader = new BufferedReader(new FileReader(answerPath));
                PrintWriter gradeWriter = new PrintWriter(new FileWriter(gradePath));
                String exercises, answer;
                int c = 0, w = 0;
                StringBuilder correct = new StringBuilder("Correct: %d (");
                StringBuilder wrong = new StringBuilder("Wrong: %d (");
                while ((exercises = exercisesReader.readLine()) != null && (answer = answerReader.readLine()) != null) {
                    int exercisesPoint = exercises.indexOf(".");
                    int answerPoint = answer.indexOf(".");
                    if (exercisesPoint != -1 && answerPoint != -1) {
                        int i = Integer.valueOf(exercises.substring(0, exercisesPoint).trim());
                        Expression expression = new Expression(exercises.substring(exercisesPoint + 1));
                        Fraction ans = new Fraction(answer.substring(answerPoint + 1));
                        if (expression.getResult().equals(ans.toString())) {
                            c++;
                            correct.append(" " + i);
                            if (c % 30 == 0) {
                                correct.append("
    ");
                            }
                        } else {
                            w++;
                            wrong.append(" " + i);
                            if (w % 30 == 0) {
                                wrong.append("-r
    ");
                            }
                        }
                    }
                }
                gradeWriter.println(String.format(correct.append(" )").toString(), c));
                gradeWriter.println(String.format(wrong.append(" )").toString(), w));
                gradeWriter.flush();
                exercisesReader.close();
                answerReader.close();
                gradeWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("已经比较完成,并生成输出文件");
        }
    }

    测试

    表达式的输出

    随机输出10条20范围以内的表达式和答案

    表达式:                                                                    结果:

                      

    对比上面输出的10条表达式和答案,结果

    然后故意修改第2,5,6,7道题的答案,再重新运行一遍,结果如下

    随机输出10000条20范围以内的表达式和答案:

            

    项目小结

            我觉得这次程序的编写,让我对开发程序有了更深入的了解,体会到沟通与合作的重要性。这次作业的结对队友郑冠华,从讨论需求到编写代码的过程中都帮助了我很多,我觉得我需要提升的地方还有很多,以后还需要继续努力,多加练习。。

    10000条表达式

  • 相关阅读:
    第19篇 2016年计划
    第18篇 我的中国梦
    Linux中文件实时同步
    Ansible Playbook
    Ansible简介及常用模块
    HTTP协议简单认识
    zabbix 分布式监控Proxy
    Zabbix中Agent自动注册
    Groovy基础语法
    Python文件操作
  • 原文地址:https://www.cnblogs.com/yhp1106/p/9715590.html
Copyright © 2020-2023  润新知