个人作业1

——四则运算题目生成程序(基于控制台)

源代码地址:https://git.coding.net/pyj76566/Homework.git

a.需求分析:

 自动生成小学四则运算题目的命令行 “软件”,满足以下需求:   

  1. 除了整数以外,还要支持真分数的四则运算,真分数的运算,例如:1/6 + 1/8 = 7/24
  2. 运算符为 +, −, ×, ÷
  3. 并且要求能处理用户的输入,并判断对错,打分统计正确率。
  4. 要求能处理用户输入的真分数, 如 1/2, 5/12 等
  5. 使用 -n 参数控制生成题目的个数,例如执行下面命令将生成10个题目
    Myapp.exe -n 10

b.功能设计:

  基本满足上述的功能

c.设计实现:

  本程序是通过java来实现的,一共有四个类和一个执行类。Fraction类表示分数,RandomGenerator类表示随机生成式子的类;User类表示用户访问类;Calculator类表示计算类。通过new一个User的实例提醒用户输入题数,这个输入函数中实例化一个RandomGenerator对象,生成一个等式。而RandomGenerator类的计算通过Calculator类,内部的参数是Fraction类型的。

d.代码说明:

  Fraction类表示的是分数这个类,只有两个属性:分子和分母,重要的函数有:makeItProper():对随机传进参数化简的功能,public Fraction(String trim):还有其中一个构造函数是对传入分数字符串生成一个Fraction实例;RandomGenerator类表示的是随机生成一个式子的类,属性:两个分数、一个结果分数、操作符的下标,操作符的数组,重要函数有:getRandomPara():随机生成一个分数,calResult():计算等式的结果;Calculator类内部都是静态的方法,通过传入两个Fraction类的参数,返回计算后的Fraction;User类属性有:rightNum和totalNum,方法有两个:getCorrectRate()方法和userInput()方法。

具体代码:

Fraction类: 

 1 package component;
 2 
 3 public class Fraction {
 4     private int numerator;
 5     private int divisor;
 6 
 7     public Fraction() {
 8         super();
 9     }
10 
11     public Fraction(int numerator, int divisor) {//构造出对象时就对其进行化简
12         this.numerator = numerator;
13         this.divisor = divisor;
14         makeItProper();
15     }
16 
17     public Fraction(String trim) {//利用正则表达式对其检测,并且分离字符串,生成Fraction对象,考虑分母为0的情况
18         if (trim.trim().matches("0")) {
19             numerator = 0;
20             divisor = Integer.MAX_VALUE;
21         } else if (trim.trim().matches("[0-9]+")) {
22             numerator = Integer.parseInt(trim);
23             divisor = 1;
24         } else if (trim.trim().matches("[0-9]+/[0-9]+")) {
25             String[] result = trim.split("/");
26             numerator = Integer.parseInt(result[0].trim());
27             if (Integer.parseInt(result[1].trim()) != 0)
28                 divisor = Integer.parseInt(result[1].trim());
29             else {
30                 System.out.println("what you inputed is valid~!");
31                 divisor = Integer.MAX_VALUE;
32             }
33 
34         } else {
35             System.out.println("what you inputed is valid~!");
36         }
37     }
38 
39     public int getNumerator() {
40         return numerator;
41     }
42 
43     public void setNumerator(int numerator) {
44         this.numerator = numerator;
45     }
46 
47     public int getDivisor() {
48         return divisor;
49     }
50 
51     public void setDivisor(int divisor) {
52         this.divisor = divisor;
53     }
54 
55     public static int commonDivisor(int m, int n) {//计算最大公约数,可以用作化简和通分
56         while (m % n != 0) {
57             int temp = m % n;
58             m = n;
59             n = temp;
60         }
61         return n;
62     }
63 
64     public void makeItProper() {//通过计算出的最大公约数进行化简
65         int commondivisor = Fraction.commonDivisor(numerator, divisor);
66         this.numerator = numerator / commondivisor;
67         this.divisor = divisor / commondivisor;
68     }
69 
70     @Override
71     public boolean equals(Object obj) {//覆盖equals函数,当且仅当分子和分母都相等,才返回true
72         // TODO Auto-generated method stub
73         if (obj instanceof Fraction)
74             return this.numerator == ((Fraction) obj).numerator && this.divisor == ((Fraction) obj).divisor;
75         return false;
76     }
77 
78     @Override
79     public String toString() {//对其格式化输出,唯一特殊的是整数
80         if (numerator % divisor == 0) {
81             return String.format("%d", numerator / divisor);
82         }
83         return numerator + "/" + divisor;
84     }
85 }
Fraction

RandomGenerator类: 

 1 package component;
 2 
 3 import java.util.Random;
 4 
 5 public class RandomGenerator {
 6     protected Fraction para1;
 7     protected Fraction para2;
 8     protected Fraction result;//直接计算出结果
 9     protected int operator;//通过下标来确定符号
10     protected final String[] operators = { "+", "-", "×", "÷" };
11 
12     public RandomGenerator() {//对分数和计算符号进行随机化
13         para1 = this.getRandomPara();
14         para2 = this.getRandomPara();
15         operator = (new Random()).nextInt(4);
16     }
17 
18     public Fraction getRandomPara() {//随机分数
19         Random r = new Random();
20         int m = r.nextInt(20) + 1;
21         int n = r.nextInt(20) + 1;
22         if (r.nextBoolean()) {
23             return new Fraction(m * n, n);
24         } else {
25             while (m > n) {
26                 m = r.nextInt(20) + 1;
27                 n = r.nextInt(20) + 1;
28             }
29             return new Fraction(m, n);
30         }
31     }
32 
33     public Fraction getPara1() {
34         return para1;
35     }
36 
37     public void setPara1(Fraction para1) {
38         this.para1 = para1;
39     }
40 
41     public Fraction getPara2() {
42         return para2;
43     }
44 
45     public void setPara2(Fraction para2) {
46         this.para2 = para2;
47     }
48 
49     public Fraction calResult() {
50         switch (operator) {
51         case 0:
52             result = Calculator.addFraction(para1, para2);
53             break;
54         case 1:
55             checkSubValue();//减法考虑结果为负数,如果是,则交换参数
56             result = Calculator.subFraction(para1, para2);
57             break;
58         case 2:
59             result = Calculator.mulFraction(para1, para2);
60             break;
61         case 3:
62             result = Calculator.devideFraction(para1, para2);
63             break;
64         }
65         return result;
66     }
67 
68     public void checkSubValue() {//考虑两个数的大小
69         int lcm = (para1.getDivisor() * para2.getDivisor())
70                 / Fraction.commonDivisor(para1.getDivisor(), para2.getDivisor());
71         int numerator1 = (lcm / para1.getDivisor()) * para1.getNumerator();
72         int numerator2 = (lcm / para2.getDivisor()) * para2.getNumerator();
73         if (numerator1 < numerator2) {
74             Fraction temp = new Fraction(para1.getNumerator(), para1.getDivisor());
75             para1.setNumerator(para2.getNumerator());
76             para1.setDivisor(para2.getDivisor());
77             para2.setNumerator(temp.getNumerator());
78             para2.setDivisor(temp.getDivisor());
79         }
80     }
81 
82     @Override
83     public String toString() {
84         if (operator == 1) {
85             checkSubValue();
86         }
87         return para1 + " " + operators[operator] + " " + para2 + " = ";
88     }
89 }
RandomGenerator

Caculator类:

 1 package component;
 2 
 3 public class Calculator {//加减乘除的计算,唯一特殊的是減法的結果为0,额外考虑
 4     public static Fraction addFraction(Fraction para1, Fraction para2) {
 5         int lcm = (para1.getDivisor() * para2.getDivisor())
 6                 / Fraction.commonDivisor(para1.getDivisor(), para2.getDivisor());
 7         int numerator1 = (lcm / para1.getDivisor()) * para1.getNumerator();
 8         int numerator2 = (lcm / para2.getDivisor()) * para2.getNumerator();
 9         return new Fraction(numerator1 + numerator2, lcm);
10     }
11 
12     public static Fraction subFraction(Fraction para1, Fraction para2) {
13         int lcm = (para1.getDivisor() * para2.getDivisor())
14                 / Fraction.commonDivisor(para1.getDivisor(), para2.getDivisor());
15         int numerator1 = (lcm / para1.getDivisor()) * para1.getNumerator();
16         int numerator2 = (lcm / para2.getDivisor()) * para2.getNumerator();
17         return (numerator1 == numerator2) ? new Fraction("0") : new Fraction(numerator1 - numerator2, lcm);
18     }
19 
20     public static Fraction mulFraction(Fraction para1, Fraction para2) {
21         return new Fraction(para1.getNumerator() * para2.getNumerator(), para1.getDivisor() * para2.getDivisor());
22     }
23 
24     public static Fraction devideFraction(Fraction para1, Fraction para2) {
25         return new Fraction(para1.getNumerator() * para2.getDivisor(), para1.getDivisor() * para2.getNumerator());
26     }
27 }
Calculator

User类: 

 1 package component;
 2 
 3 import java.util.Scanner;
 4 
 5 public class User {
 6     private int rightNum = 0;//正确的数目
 7     private int totalNum = 0;//总数目
 8 
 9     public String getCorrectRate() {//计算正确率
10         if (totalNum == 0)//0的情况特殊,另外输出
11             return "0.0%";
12         return String.format("%s %.2f %s", "The correct rate is :", (((double) rightNum) / totalNum) * 100, "%");
13     }
14 
15     public void userIntput(String arg) {//用户输入函数,由于输入之前已经检测过,无需再检测
16         Scanner sc = null;
17         String temp;
18         temp = arg.trim();
19         totalNum = Integer.parseInt(temp);
20         for (int i = 0; i < totalNum; i++) {
21             RandomGenerator rg = new RandomGenerator();
22             System.out.println("******************************************************");
23             System.out.print(rg);
24             sc = new Scanner(System.in);
25             if (sc.hasNextLine()) {
26                 Fraction result = new Fraction((sc.nextLine()));
27                 if (result.equals(rg.calResult())) {
28                     this.rightNum++;
29                     System.out.println(String.format("%20s", "right!"));
30                 } else {
31                     System.out.print(String.format("%20s", "false!"));
32                     System.out.println("   **the correct answer is:" + rg.calResult());
33 
34                 }
35 
36             }
37         }
38         System.out.println("******************************************************");
39         System.out.println(
40                 "Finished! The total questions are:" + this.totalNum + ",and the right questions are:" + this.rightNum);
41         System.out.println(this.getCorrectRate());
42     }
43 
44 }
User

执行类: 

 1 package component;
 2 
 3 public class GeneratorTester {
 4     public static void main(String[] args) {//对输入参数提示和限制
 5         User u = new User();
 6         String num = null;
 7         if (args.length > 0) {
 8             if (args[0].trim().equals("-n") && args.length == 2 && args[1].matches("[0-9]+")) {
 9                 num = args[1];
10                 u.userIntput(num);
11             } else
12                 System.out.println("Parameter formating valid! The standard format is -n digital");
13         } else {
14             System.out.println("No defined parameter");
15         }
16     }
17 }
GeneratorTester

e.测试运行:

1.首先对控制台输入的时候 进行参数检测:

2.对用户的输入的结果进行检测

PSP表:

PSP2.1 Personal Software Process Stages Time (%) Senior Student Time (%)
Planning 计划 8min 10min
· Estimate 估计这个任务需要多少时间 2min 2min
Development 开发 ? ?
· Analysis 需求分析 (包括学习新技术) 3min 10min
· Design Spec 生成设计文档 5min 6min
· Design Review 设计复审 10min 15min
· Coding Standard 代码规范 ? ?
· Design 具体设计 15min 20min
· Coding 具体编码 1h 3h
· Code Review 代码复审 15min 20min
· Test 测试(自我测试,修改代码,提交修改) 13min 21min
Reporting 报告 1h 1.2h
· 测试报告 5min 5min
· 计算工作量 10min 8min
· 并提出过程改进计划 5min 5min

 

小结:

  这次作业难度不高,但是也花费了我挺久的时间,主要是我没有对这个题目进行全面的认识,而且没有好好规划,所以造成了“超时”完工。虽然题目很简单,但是在思考过程中还是得考虑很多东西,比如说分母不为0的问题,减法减出分数的控制问题,覆盖Fraction的equals()问题等等。不过“阿超”完成这个程序的速度也太快了吧,20分钟?看来我的经验还是有很多不足。还有就是拓展性的问题,就以Java来说,设计好类与类之间的关系十分重要,对你的维护以及功能拓展有很大的便捷,不然就十分有可能重新设计,导致工作量增加。所以我觉得可以去看一些关于程序设计的书。至于本程序的扩展,我暂时考虑到的是多项的扩展,因为RandomGenerator类是一个等式,如果要增加项数的话,可以考虑再写一个类Decorator,它和RandomGenerator一起继承一个抽象类,假设是Component,这个类有两个属性,String description 和 Fraction result,表示它的式子和最后的结果,抽象方法有getDecription()和getResult();而Decorator类中有Component引用属性,假设是obj,当要实现抽象类的方法时,getResult()返回的是obj.CalReult()与Decorator类的Fraction引用属性的计算值,至于符号就随机生成,这样当new Decorator(obj)时,getResult()可以得到新的结果,同理getDescription(),至于实现,其实没有这么简单,还要考虑随机生成的问题,以及Decorator类这个新生成后缀的符号和obj内符号之间优先级的问题,总之还是要注意很多的。

 

2017-03-02 15:24:38

posted @ 2017-03-02 15:27  pyj086  阅读(536)  评论(2编辑  收藏  举报