四则运算 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("\r\n");
                        }
                    } else {
                        w++;
                        wrong.append(" " + i);
                        if (w % 30 == 0) {
                            wrong.append("-r\n");
                        }
                    }
                }
            }
            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范围以内的表达式和答案:

        

项目小结

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

原文地址:https://www.cnblogs.com/yhp1106/p/9715590.html

时间: 2024-10-31 18:59:10

四则运算 Java 杨辉鹏,郑冠华的相关文章

java杨辉三角和空心菱形(二维数组篇)

一.杨辉三角 1 import java.util.Scanner; //导入包 2 public class Test7 { 3 public static void main(String[]args){ 4 5 Scanner row=new Scanner(System.in); //调用扫描器 6 int n = row.nextInt(); //定义类型 7 int [][] a=new int[n][n]; //定义二位数组 8 int i,j; //声明整型 9 10 for(i

使用Java打印杨辉三角

package 杨辉三角; import java.util.Scanner; public class 三角 { private static Scanner scn; public static void main(String[] args) { scn = new Scanner(System.in); System.out.println("请输入数据"); int n = scn.nextInt(); //定义一个二维数组 int [][] array = new int

Java的二维数组的应用及杨辉三角的编写

(1) 编写一个程序,生成一个10*10的二维随机整数数组,并将该数组的每行最大值保存于一个一维数组中,将每列平均值保存于另外一个一维数组中并分别输出. (2) 编程输出杨辉三角的前10行. 找出一个,即该位置上的元素在该行上最大,在该列上最小(注:一个二维数组也可能没有这样的鞍点). /** * * @author liuhui *@version Java上机实验三 *@time 2016.10.30 */ public class javatest2 { public static int

Pascal&#39;s Triangle leetcode java(杨辉三角)

题目: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5, Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 题解:既然讲到了Pascal‘s Triangle,即杨辉三角.那么就先去Wikipedia上面复习一下杨辉三角吧:”杨辉三角形,又称賈憲三角形.帕斯卡三角形.海亚姆三角形,是二项式係數在的

输出杨辉三角(C++和 JAVA版 )

C++版本: #include <iostream> using namespace std; void main() { int n=10; while(n!=-1) { cout<<"请输入 杨辉三角 行数:"; cin>>n; int **a = new int* [n]; for(int m = 0; m < n; m++) { a[m] = new int [n]; } for(int i=0;i<n;i++) { for(in

【LeetCode-面试算法经典-Java实现】【119-Pascal&#39;s Triangle II(帕斯卡三角形(杨辉三角)II)】

[119-Pascal's Triangle II(帕斯卡三角形(杨辉三角)II)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3,3,1]. Note: Could you optimize your algorithm to use only O(k) extra

Java之杨辉三角的实现

今天突然想温习一下Java的基础,想了想就写写杨辉三角吧 1 public class First 2 { 3 public static void main(String[] args) 4 { 5 int[][] Arr = new int[5][]; 6 for(int i = 0; i < Arr.length; i++) 7 { 8 Arr[i] = new int[i + 1]; 9 Arr[i][0] = 1; 10 Arr[i][i] = 1; 11 for(int j = 0;

hdu 2032 杨辉三角 (java)

问题: 本题要求看出杨辉三角的规律,即:a[i][j]=a[i-1][j-1]+a[i-1][j]; 在输出的时候第一列没有输出,原因是j参数设置的是从1开始的,故将其改为0,用if满足j从一开始的需求就可以了. 杨辉三角 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 43154    Accepted Submission(s):

Java基础------杨辉三角(递归实现)

  第一列 第二列 第三列 第四列 第五列 第六列 第七列 第八列 第九列 第十列 第十一列 ...... 第一行 第一个空格  第二个空格  第三个空格  第四个空格 第五个空格 1             第二行 第一个空格 第二个空格  第三个空格 第四个空格 1   1           第三行 第一个空格 第二个空格  第三个空格 1   2   1         第四行 第一个空格 第二个空格 1   3   3   1       第五行 第三个空格 1   4   6   4