2016011993+小学四则运算练习软件项目报告

仓库地址:https://git.coding.net/DandelionClaw/CalculateProject.git

 

1.需求分析:

   Ⅰ程序可接收一个输入参数n,然后随机产生n道加减乘除(分别使用符号+-*÷来表示)练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间。

   Ⅱ每个练习题至少要包含2种运算符。不能存在分数、负数与非整数。

 

2.功能设计:

①基本功能:

   Ⅰ 在用户输入错误数据时提示

   Ⅱ 自动随机生成用户输入个数的算式,并给出算式答案

   Ⅲ 将结果生成为文件,如果存储错误会提示

②扩展功能

  Ⅰ 考虑到小学生计算水平,将算式结果约束在0~100间

  Ⅱ 随机产生括号并保证算式正确性

  Ⅲ 在用户输入的算式数中,一半是(随机)带括号的普通四则运算算式,一半是分数算式

 

3.设计实现:

定义了算式“Formula”类,用于定义算式和定义静态变量加减乘除,createString()方法用于生成算式字符串,setOps()方法用于生成算式类的每个操作符,setAns()方法用于计算每个算式的结果。

定义了分数算式“Fraction”类,它继承了Formula类,并扩展出了getFraction()方法用于生成分式,gcd()方法用于计算两数最大公因数。

在普通的四则运算中createFormula()函数用于生成算式。

在分数四则运算中createFormulaWithFraction()函数用于生成算式。

createFile()函数用于生成文件。

关系如下图所示

 

4.算法详解:

对于生成题目,我用到了随机函数库Random,先随机生成操作符,再随机生成参数,通过判断操作符是否是除法和减法再调整参数。

对于生成答案,我的第一反应是利用算法通过堆栈实现,但是我脑海中突然浮现出另一个想法。在寒假自学的Python中有一个函数eval()可以把字符串转换成表达式,这个方法刚好适用于此时的情形。虽然Java没有eval函数,但是JavaScript有。Python和JavaScript都是脚本函数,只要使用ScriptEngine调用js脚本即可调用eval函数。我先设计了getString()函数得到每个算式的字符串表达,然后通过上述方法轻松实现字符串到算术的转换。

 对于求最大公因数,我使用了运用辗转相除法的递归方法求得。

对于括号的添加,我先设定一个参数isbracket,用随机函数生成其值,若为1则该算式含括号,若为0则不含。含括号时,我再使用随机函数产生上括号所在位置,然后再计算出下括号位置,添加在字符串中。

 

5.测试运行:

 

 

 

6.代码展示:

public void setAns() throws ScriptException//算术表达式结果计算函数
        {
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine se = manager.getEngineByName("js");
            this.ans = (Integer) se.eval(this.str);
        }

 

 1 public void setOps() {//随机生成操作符函数
 2             Random r = new Random();
 3             for(int i=1;i<=this.num_of_operation;i++){
 4                 this.ops[i] = r.nextInt(4);
 5                 if(this.ops[i]==3&&this.ops[i-1]==3){
 6                     this.ops[i-1]=r.nextInt(2);
 7                 }
 8             }
 9             //排除符号单一情况
10             boolean flag = true;
11             for(int i=2;i<=this.num_of_operation;i++){
12                 if(this.ops[i]!=this.ops[i-1]){
13                     flag = false;
14                 }
15             }
16             if(flag){
17                 do{
18                     this.ops[2] = r.nextInt(3);
19                 }
20                 while(this.ops[2]==this.ops[1]);            
21             }
22         }

 

public int gcd(int x, int y){ //求最大公约数
                if(y == 0)
                        return x;
                 else
                        return gcd(y,x%y);
        }

 

7.总结:

对于软件模块化,我将程序的每个功能都单独作为函数独立出来,实现了可复用性和可维护性。先列出各功能(函数)的关系,形成结构框架,然后自顶向下设计,逐步求精,完成各函数的编写。 

 

8.PSP展示:

 

任务内容

计划共完成需要的时间(min)

实际完成需要的时间(min)

计划

10

8

·   估计这个任务需要多少时间,并规划大致工作步骤

10

8

开发

246

326

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

6

10

·         生成设计文档

5

5

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

5

6

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

5

3

·         具体设计

10

12

·         具体编码

180

203

·         代码复审

5

9

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

30

78

报告

10

9

·         测试报告

3

2

·         计算工作量

2

1

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

5

6

我在具体编码时间和测试时间两栏远远超过了计划。

原因是在具体编码时我低估了算法的复杂性,在乘法方面可能会导致算式结果过大,因在这方面调整算法。

在测试时,出现了一个bug,经排查,是在保证计算无小数时,我使用调整算式参数的方法,但我在调整参数之前就已经把参数输入字符串,导致最后的结果仍是未经更改有小数的。之后又花了大量的时间反复修改,精简代码。

 

posted @ 2018-03-22 20:12  DandelionClaw  阅读(269)  评论(2编辑  收藏  举报