作业2-MathExam V2.0
- MathExam V2.0
一、预估与实际
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 50 |
• Estimate | • 估计这个任务需要多少时间 | 20 | 50 |
Development | 开发 | 390 | 715 |
• Analysis | • 需求分析 (包括学习新技术) | 60 | 120 |
• Design Spec | • 生成设计文档 | 60 | 60 |
• Design Review | • 设计复审 | 20 | 50 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 20 | 15 |
• Design | • 具体设计 | 50 | 50 |
• Coding | • 具体编码 | 120 | 300 |
• Code Review | • 代码复审 | 50 | 120 |
• Test | • 测试 (自我测试,修改代码,提交修改) | 10 | 60 |
Reporting | 报告 | 30 | 40 |
• Test Repor | • 测试报告 | 10 | 20 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• 事后总结,并提出过程改进计划 | 10 | 10 | |
Postmortem & Process Improvement Plan | 合计 |
二、需求分析
我通过观察家长们的要求了解到,小学三年级四则混合运算有如下的几个特点:
- 运算符在2~4个【进一步细化要求:至少两个不同的运算符】
- 可以加括号
- 减法运算的结果不能有负数
- 除法运算除数不能为0,不能有余数
经过分析,我认为,这个程序应当:
- 不可输入除数字外其他字符
- 注意辨别命令行参数个数
- 保留小学一年级和小学二年级计算题生成的功能,同时增加小学三年级四则混合运算的生成功能
- 随机生成括号改变优先级
三、设计
1. 设计思路
说明你如何设计这个程序
比如:
- 通过命令行接收参数
- 通过函数来随机生成题目
- 计算四则算式
- 最后生成题目与答案文件
- 关键函数是题目的生成函数认真构思
2. 实现方案
- 逆波兰表达式
四、编码
请说明你如何按照设计思路进行编码,并记录你在开发中遇到的问题,与解决过程
1. 调试日志
- 第一次编译测试,括号位置不正确
- 第二次编译测试,括号无法提高优先级
2. 关键代码
public static int Random(int Min, int Max) {
return (int) (Min + Math.random() * (Max - Min + 1));
}
public static int Calc(String Question) {
Stack<Integer> nums = new Stack<Integer>(); // 栈 保存数字
Stack<Character> opes = new Stack<Character>(); // 栈 保存操作符
String string = Question.replace(" ", "");// 获取临时字符串
char symbol;
int n = 0; // 保存每一个数字
char[] cs = string.toCharArray();// 字符串转换为char数组
for (int i = 0; i < cs.length; i++) {// 遍历char数组
char temp = cs[i];
if (Character.isDigit(cs[i])) {// 判断当前char是否为数字
n = 10 * n + Integer.parseInt(String.valueOf(temp)); // 临时保存大于10的数字
} else {// 非数字
if (n != 0) {
nums.push(n);// 数字入栈
n = 0;
}
if (temp == '(') {// 如果遇到左括号
opes.push(temp);// 入栈
} else if (temp == ')') {// 如果是遇到右括号
while (opes.peek() != '(') { // 括号里面运算完(查看堆栈顶部的对象,但不从堆栈中移除它)
symbol = opes.pop();
int t = cal(nums.pop(), nums.pop(), symbol);// 计算两个数据
if (t < 0 && symbol == '-') {
return -1;
}
if (t == 0 && symbol == '÷') {
return -1;
}
if (t < 0 && symbol == '÷') {
return -1;
}
nums.push(t);// 计算结果入栈
}
opes.pop();
} else if (isType(temp) > 0) {
if (opes.isEmpty()) { // 栈为空直接入栈
opes.push(temp);
} else {
// 若栈顶元素优先级大于或等于要入栈的元素,将栈顶元素弹出并计算,然后入栈
if (isType(opes.peek()) >= isType(temp)) {
symbol = opes.pop();
int t = cal(nums.pop(), nums.pop(), symbol);// 计算两个数据
if (t < 0 && symbol == '-') {
return -1;
}
if (t == 0 && symbol == '÷') {
return -1;
}
if (t < 0 && symbol == '÷') {
return -1;
}
nums.push(t);
}
opes.push(temp);
}
}
}
}
// 最后一个字符若是数字,未入栈
if (n != 0) {
nums.push(n);
}
while (!opes.isEmpty()) {
symbol = opes.pop();
int t = cal(nums.pop(), nums.pop(), symbol);// 计算两个数据
if (t < 0 && symbol == '-') {
return -1;
}
if (t == 0 && symbol == '÷') {
return -1;
}
if (t < 0 && symbol == '÷') {
return -1;
}
nums.push(t);
}
return nums.pop();
}
3. 代码规范:
- 采用4个空格缩进,禁止使用tab字符。
- 左小括号和字符之间不出现空格;同样的,有小括号和字符之间也不出现空格
- 注释的双斜线与注释内容之间有且仅有一个空格
- 大括号的使用约定
- 方法参数在定义和传入是,多个参数逗号后边必须加空格
- 没有必要增加若干空格来是耨一行的字符与上一行对应位置的字符对齐
- 不同逻辑、不同语义、不同业务的代码之间插入一个空行分割开来以提升可读性
- 任何二目、三木运算符的左右两边都需要加一个空格
五、测试
- 命令:
java MathExam -n 5 -Grade 1
- 输出:
(1) 40 - 38 =
(2) 2 + 38 =
(3) 81 - 10 =
(4) 42 + 57 =
(5) 79 - 17 =(1) 40 - 38 = 2
(2) 2 + 38 = 40
(3) 81 - 10 = 71
(4) 42 + 57 = 99
(5) 79 - 17 = 62
- 命令:
java MathExam -Grade 3 -n 5
- 输出:
(1) 36 × 17 + 75 ÷ 1 + 91
(2) ( 13 + 93 ) × 17
(3) 97 + 21 + 44 - 89 + 73
(4) 4 × 64 + 23 + 18 + 9
(5) 1 × 58 × 57 × 86 - 96
(1) 96 × 5 + 68 ÷ 91 + 20 = 778
(2) ( 13 + 93 ) × 17 = 1802
(3) 7 + 55 + 57 - 53 + 32 = 146
(4) 55 × 85 + 100 + 95 + 74 = 306
(5) 65 × 96 × 71 × 92 - 52 = 284220
- 命令:
java MathExam Grade 2 -n
- 输出:
Error:001
六、总结
请总结过程中的教训和经验,思考
- 结对编程相比单独编程效率更高
- 需求分析非常重要
- 掌握多门语言非常重要
- 代码目前3/4运算符加括号问题暂时没有解决,且运行时可能崩溃