2016012002+小学四则运算练习软件项目报告
项目报告目录:
一、感想
二、需求分析
三、功能设计
四、设计实现
五、算法详解
六、测试运行
七、总结反思
八、PSP展示
代码仓库地址:https://git.coding.net/Vsmile1997/sizeys.git测试效果见src下生成的result.txt文件
一、感想
我把感想写在第一部分,是想首先谈谈完成这个项目的体验和感悟。重新梳理程序的代码思路,满满的完成任务的成就感和如释重负的轻松感。从拿到作业的起初,我把问题过度放大了。Java?我还要重新拿起那本大厚书学习Java?出于懒惰,我还是硬着头皮慢慢做,遇到什么困难就现学现卖。从随机数的产生,括号的分配,算式的合法化到堆栈的建立,优先级的处理……编写程序的过程就像是建造大楼一样,自己有很多想法。一次次的摸索与肯定,一次次的推翻与重建。逻辑的正确表达,代码的标准实现,这个过程尽管有些虐心,但是困难恰是自己进步的机会,不断地积淀着成就感。这一周因为这次作业而倍感充实,这次的项目也让我认识到自己的不足以及对以往知识的负债。借此机会,认真梳理代码思路,把知识从厚变薄,又从薄变厚,这个过程就是回顾总结的机会。
二、需求分析
现在需要面向小学生设计一款四则运算出题软件,减轻老师和家长的辅导负担,同时提高小学生的运算思考能力。
1.对象分析:考虑到出题软件面向小学生主体,软件设计的细节应当做到:
(1)运算数字以0-100的整数为宜,运算符以3-5个为宜,一道题中至少出现两种运算符;
(2)每一步计算结果避免出现负数,除法运算需保证整除;
(3)支持有括号运算,算式中存在的括号必须大于2个,且不得超过运算符的个数;
(4)支持真分数的加减运算(不含乘除运算),每一步计算结果需保证均为真分数,结果要求最简化。
2.软件分析:对于软件设计和用户体验,基本要求如下:
(1)采用JAVA语言编程设计软件;
(2)程序可接收一个输入参数n,然后随机产生n道加减乘除(分别使用符号+-*÷来表示)练习题;
(3)练习题生成好后,将学号与生成的n道联系题及其对应的正确答案输出到文件“result.txt”中;
(4)处理错误的测试数据并给出提示。
三、功能设计
这款四则运算软件包括基本功能和拓展功能两部分,以满足不同层次,不同
知识水平的小学生的实际需求。
1.基本功能:(1)实现100以内的整数的四则混合运算,运算符3-5个且一道题至少两种运算符;
(2)计算过程和结果没有负数出现和非整除的情况出现。
2.拓展功能:(1)有括号计算且存在的括号个数大于2个但不超过运算符的个数;
(2)真分数的加减运算(不含乘除运算),每一步计算结果需保证均为真分数,结果要求最简化。
四、设计实现
结合基本功能和拓展功能,将主程序分为两大模块:整数计算和真分数计算。在整数计算中,包含了生成算数表达式和计算结果两个部分,考虑到操作符的优先级问题,附带一个优先级比较判断的函数;在真分数计算中,包含了生成算数字符串和计算结果两个部分,考虑到分式的化简问题,附带一个求解两个整数最大公约数的函数。设计实现的模块化函数如下图:
五、算法详情
1.生成与计算:我采取的方式是边生成边运算,生成与运算同步以便检查算式的合法性。
(1)整数算式:运算过程和结果满足非负性,整除且除数不为零。
1 ... 2 ... 3 if(opt[type]=='-')//如果是减法 4 { 5 while(s1<s2); //被减数小于减数,则重新生成减数 6 s2=(int)(Math.random()*100); 7 sum=s1-s2;//保证减法合法 8 } 9 ... 10 ... 11 if(opt[type]=='÷')//如果是减法 12 { 13 while(s2==0||s1%s2!=0)//不能整除或除数为0,重新生成除数 14 s2=(int)(Math.random()*100+1); 15 sum=s1/s2;//保证除数合法 16 }
(2)真分数算式:真分数定义要求分子小于分母且分子不为零,运算过程和结果均为真分数。
1 ... 2 ... 3 int fz1=(int)(Math.random()*10+1); //生成分子 4 int fm1=(int)(Math.random()*30+11); //生成分母 5 if(fz1>=fm1) //如果分子大于等于分母 6 fm1=fz1+fm1;//令fm1=fz1+fm1,使分式合法 7 int div1=gcd(fz1,fz1); 8 fz1=fz1/div1; 9 fm1=fm1/div1; //化简过程 10 ... 11 ... 12 type=(int)(Math.random()*2);//下面j为操作符个数,是一个循环控制量 13 if(fm1==fm2)//分母相同 14 { 15 fm=fm1;//分母不变 16 if(type==0)//减法运算 17 { 18 fz=fz1+fz2;//分子相加 19 if(fz>=fm)//分式大于1,重新生成分式 20 j--; 21 else 22 { 23 int div=gcd(fz,fm);//化简 24 fz/=div; 25 fm/=div; 26 fra1=fra1+""+opt[type]+fz2+"/"+fm2; 27 fz1=fz; 28 fm1=fm; 29 } 30 } 31 else//减法运算 32 { 33 fz=fz1-fz2; //分子相减 34 if(fz<=0)//分式不合法,重新生成 35 j--; 36 else 37 { 38 int div=gcd(fz,fm); 39 fz/=div; 40 fm/=div; 41 fra1=fra1+""+opt[type]+fz2+"/"+fm2; 42 fz1=fz; 43 fm1=fm; 44 } 45 } 46 ... 47 ...
2.调用函数:分为优先级判断和最大公约数两个函数。
(1)优先级判断:通过对操作符的优先级进行比较,判断是否添加括号,括号有实际意义。
1 public static int youxianji(char c)// 判断优先级 2 { 3 if (c == '*' || c == '÷') //乘除优先级最高 4 return 3; 5 if (c == '+' || c == '-') 6 return 2; 7 if (c == '(') 8 return 1; 9 return 0; 10 }
(2)最大公约数:在化简分数时,分子分母需要同时除以一个不为零的最大公约数,以保证分式最简化。
1 //最大公因数,每次代入,显然有a<b 2 public static int gcd(int a, int b)//每次代入分子和分母,不需判断a,b大小 3 { 4 while(a!=0) 5 return gcd(b % a, a); 6 return b; 7 } 8
六、测试运行
按照要求,进行程序的测试与运行,结果如下:
1.合法参数输入:
注:上图中第一个算式除数生成的始终为1,是因为边算边生成时,(60+41)为质数,在保证整除的情况下,除数只能生成1。(其实这样生成效率有点低)
2.非法参数输入:
七、总结反思
这个项目按照要求实现了基本功能和拓展功能,在程序的布局上,尽量采用模块化编程,增加了程序的可读性和可移植性,便于后期对程序的修改和完善。但是,对于算法和语言的要求有所瑕疵。在编程过程中,我始终使用C/C++做题。直到功能实现后,我才慢慢力求将C/C++的语言风格改为JAVA。比如,符号的选择比较:C语言用(char==’+’)就可以实现目的,而JAVA需要(char.equals("÷")) ,功能一样,但是语言风格迥异。对于同一算式中,要求至少存在两种,我仅仅是将倒数第二个符号的下标自增1,这样虽然达到了要求,但是并不是很好。诸如此类繁冗的有待进一步优化的地方,一定还存在着,需要我后期继续琢磨,不断修改。
八、PSP展示
PSP |
任务内容 |
计划时间(min) |
完成时间(min) |
Planning |
计划 |
10 |
5 |
Estimate |
估计与规划 |
10 |
20 |
Development |
开发 |
300 |
700 |
Analysis |
需求分析 |
10 |
20 |
Design Spec |
生成文档 |
30 |
45 |
Design Review |
设计复审 |
20 |
30 |
Coding Standard |
代码规范 |
30 |
60 |
Design |
具体设计 |
240 |
500 |
Coding |
具体编码 |
60 |
200 |
Code Review |
代码复审 |
30 |
60 |
Test |
测试 |
20 |
50 |
Reporting |
报告 |
60 |
180 |
Test Report |
测试报告 |
10 |
30 |
Size Measurement |
计算工作量 |
20 |
45 |
Postmortem & Process Improvement Plan |
事后总结并改进 |
30 |
50 |