2016012051 小学四则运算练习软件项目报告
小学四则运算练习软件项目报告
项目地址:https://git.coding.net/Cathellina/Week2-2.git
修改过程:http://www.cnblogs.com/Cathelina/p/8888016.html
————————————————————————————————————————————
目录
一、需求分析
二、功能设计
三、设计实现
四、算法详解
五、测试运行
六、代码展示
七、psp
八、总结
————————————————————————————————————————————
一、需求分析
(一)语言:使用JAVA编程语言;
(二)从用户角度:
1.随机产生n道加减乘除练习题;
2.由于用户主要是小学生,练习题数字范围在0~100,且不得出现负数与非整数;
3.规定每道练习题至少要包含2种运算符和3个数字;
(三)从开发者角度:
1.产生n道四则运算练习题的命令行软件;
2.练习题生成好后,将学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中,不能输出额外信息,文件目录与程序目录一致。
————————————————————————————————————————————
二、功能设计
1.程序可接收一个输入参数n,然后随机产生n道加减乘除练习题,每个练习题至少要包含2种运算符;
2.练习题数字范围在0~100,不得出现负数与非整数;
3.练习题生成好后,将你的学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中,不要输出额外信息,文件目录与程序目录一致;
4.例如当程序接收的参数为4时,以下为一个输出文件示例。
2018010203
13+17-1=29
11*15-5=160
3+10+4-16=1
15÷5+3-2=4
————————————————————————————————————————————
三、设计实现
————————————————————————————————————————————
四、算法详解
由于之前没有了解过表达式的计算方法,于是我根据老师的链接和自己查阅的一些资料,了解了调度场算法。
调度场算法(shunting yard algorithm),即逆波兰表达式是通过将中缀表达式转换为后缀表达式来简化计算的。需要注意的是其运算符遵循越往栈顶优先级越高的原则。
1.若当前运算符为'(',直接入栈;
2.若当前运算符为')',出栈并顺序输出运算符直到遇到第一个'(',遇到的第一个'('出栈但不输出;
3.若为其它,比较运算符栈栈顶元素与当前元素的优先级:
如果栈顶元素是'(',当前元素直接入栈;
如果栈顶元素优先级>=当前元素优先级,出栈并顺序输 出运算符直到栈顶元素优先级<当前元素优先级,然后当前元素入栈;
如果栈顶元素优先级<当前元素优先级,当前元素直接入栈。
4.顺序出栈并输出运算符直到栈元素为空,
5.解析后缀表达式,对逆波兰表达式求值,得到运算结果。
————————————————————————————————————————————
五、测试运行
(一)测试步骤
1.在命令行输入javac Main.java
2.回车之后输入java Main 20
3.成功
(二)测试结果
————————————————————————————————————————————
六、代码实现
调度场算法的实现
/** * 将表达式从中缀表达式转换为后缀表达式(波兰式) */ public String[] midToEnd(List midList) { Stack embl = new Stack(); Stack result = new Stack(); Iterator it = midList.iterator(); String curStr = null; while (it.hasNext()) { curStr = (String) it.next(); /* 确认是否式字符串 */ if(sign.containsKey(curStr)) { /* 如果符号栈为空 或者符号为( */ if (0 == embl.size() || "(".equals(curStr)) { embl.push(curStr); } else { /*如果符号为) 符号栈需要出栈,直到匹配一个(为止 */ if(")".equals(curStr)) { while(!"(".equals((String)embl.peek())) { if(0 >= embl.size()) { return null; } result.push(embl.pop()); } embl.pop(); } else { int p1 = Integer.parseInt((String) sign.get(curStr)); int p2 = Integer.parseInt((String) sign.get(embl.peek())); /* 如果当前字符的优先级大于栈顶符号的优先级 */ if (p1 > p2) { embl.push(curStr); } else { while (p1 <= p2 || embl.size() > 0) { result.push(embl.pop()); if(0 == embl.size()) { break; } p2 = Integer.parseInt((String) sign.get(embl.peek())); } embl.push(curStr); } } } } else { result.push(curStr); } } while (0 < embl.size()) { result.push(embl.pop()); } int len = result.size(); String[] ret = new String[len]; for (int i = 0; i < len; i++) { ret[len - i - 1] = (String) result.pop(); } return ret; }
————————————————————————————————————————————
七、展示PSP
PSP |
任务内容 |
计划共完成需要的时间(h) |
实际完成需要的时间(h) |
Planning |
计划 |
1 |
4 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
5 |
2 |
Development |
开发 |
100 |
80 |
Analysis |
需求分析 (包括学习新技术) |
40 |
100 |
Design Spec |
生成设计文档 |
2 |
1 |
Design Review |
设计复审 (和同事审核设计文档) |
1 |
0 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
1 |
1 |
Design |
具体设计 |
10 |
5 |
Coding |
具体编码 |
60 |
200 |
Code Review |
代码复审 |
4 |
40 |
Test |
测试(自我测试,修改代码,提交修改) |
100 |
320 |
Reporting |
报告 |
4 |
5 |
Test Report |
测试报告 |
2 |
1 |
Size Measurement |
计算工作量 |
1 |
1 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
1 |
2 |
根据我统计得到的PSP表,测试环节是耗时最多,而且估计和实践相差最大的环节。原因在于对java的掌握不够,总是因为一些小bug影响整个速度。
————————————————————————————————————————————
八、总结
在模块化实现方面,首先用主程序、子程序等建立一个大概的框架,把整个流程描述出来,再调整好好各个框架之间的输入、输出关系。得到一系列以功能块为单位的算法描述后再求解算法。这样不仅降低了程序复杂度,还让之后的调试阶段更加简单了。
根据我统计得到的PSP表,测试环节是耗时最多,而且估计和实践相差最大的环节。原因在于对java的掌握不够,总是因为一些小bug影响整个速度。而整个项目的主要问题则在于我对整个任务的时间计划上出现了问题,再加上java基础不好,不得不重新从头开始学习,使得之后的时间一再压缩,整个项目也一直处于紧赶慢赶的状态中。但同时,我也得到了一些收获,其中最大的收获在于了解了如何用调度场算法处理数学表达式的计算,如何让计算机按照一定的要求计算四则运算题;并且认识到自己对于java的欠缺和对项目时间的把控能力还很差,需要好好地提高。希望能够在老师和各位助教们的帮助下继续努力,追上大家的脚步。