第三次作业
第二次作业:MathExam
一、预估与实际
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 30 |
• Estimate | • 估计这个任务需要多少时间 | 240 | |
Development | 开发 | 120 | 240 |
• Analysis | • 需求分析 (包括学习新技术) | 60 | 60 |
• Design Spec | • 生成设计文档 | 60 | 60 |
• Design Review | • 设计复审 | 10 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
• Design | • 具体设计 | 20 | 20 |
• Coding | • 具体编码 | 60 | 120 |
• Code Review | • 代码复审 | 40 | 60 |
• Test | • 测试(自我测试,修改代码,提交修改) | 15 | 20 |
Reporting | 报告 | 60 | 80 |
• Test Repor | • 测试报告 | 20 | 20 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 | 20 |
合计 | 760 |
二、需求分析
经过分析,我认为,这个程序应当:
- 运算中可以添加括号,改变基础的四则运算的顺序。(运算符在2~4个且至少两个不同的运算符)未实现
- 不能出现小数,题目中出现的数字和答案结果都必须是整数
- 减法运算的结果不能有负数,除法运算除数不能为0,且所有的数字不能是余数,且保留小学一二年级的运算的出题功能。
三、设计
1. 设计思路
首先考虑题目的要求:
- 输入格式:程序需从命令行中接收两个参数 年级 和 题目数量,分别用 -n 和 -grade 表示
- 输出格式:把题目和标准答案写入out.txt文件,输出的格式要求:
(1)每道题目占一行
(2)每道题的格式- 题号:数字 + 一对英文括号
- 题目:数字、符号之间空一格
- 题号与题目之间也需要加一空格,行末不需要加空格
2. 实现方案
- 准备工作:学会逆波兰表达式,考虑题目的输出,括号的优先级
- 技术关键点:先要掌握逆波兰表达式的含义,以及为什么要使用逆波兰表达式,为什么不能使用符合平时我们更适应的中缀表达式。
运算表达式的种类: - 1.中缀表达式 a + b,运算符号在两个运算对象的中间。
- 2.前缀表达式+ - a * b c d,运算符在运算对象前面,又称为波兰表达式。
- 3.后缀表达式 a b c * - d +,运算符在运算对象后面,又称为逆波兰表达式。
后缀表达式的优点: - 1.相较于前缀表达式更易于转换,最左边一定为数字。
- 2.更符合计算机的计算方式。计算机通过从左至右读取后缀表达式,就可以将遇到的运算对象压入栈,在遇到运算符时就弹出两个运算对象,完成计算,再将结果压入栈。最后留在栈中的就是计算结果。
中缀表达式转换为后缀表达式的方法:例:a + b * c - (d + e) - 1.按照运算符的优先级对所有的运算单位加括号。((a + (b * c)) - (d + e))
- 2.转换中缀与后缀表达式后缀:把运算符号移动到对应的括号后面。((a (b c) * ) + (d e) + ) -
- 3.把括号去掉,得到后缀表达式a b c * + d e + -
首先确定四则运算的加减乘除的优先级。得到后缀表达式后,通过匹配字符,创建两个栈:输出栈和符号栈,如果匹配到的字符是数字的话,直接压入输出栈,如果匹配到运算符号,则压入符号栈,如果当前元素的优先级小于等于栈顶元素的优先级,出栈并顺序输出运算符。若当前元素的优先级大于栈顶元素的优先级,则直接入栈。
四、编码
1. 关键代码
private static void problems(int n, int grade) {
String[] fuhao = { " + ", " - ", " * ", " / " };
String fengge = "\r\n";
Random rand = new Random();
String a = "";
int S_num1 = (rand.nextInt(101));
int i = 0;
String S_wenti = S_num1 + "";
if (grade == 1) {
for (i = 1; i <= n; i++) {
int operator = (int) (Math.random() * 2);
if (operator == 0) {
int num1 = (int) (Math.random() * 10);
int num2 = (int) (Math.random() * 10);
result = num1 + num2;
wenti.append("(" + i + ") " + num1 + " + " + num2 + "\r\n");
daan.append("(" + i + ") " + num1 + " + " + num2 + " = " + result + "\r\n");
} else if (operator == 1) {
int x = (int) (Math.random() * 10);
int y = (int) (Math.random() * 10);
result = x - y;
wenti.append("(" + i + ") " + x + " - " + y + "\r\n");
daan.append("(" + i + ") " + x + " - " + y + " = " + result + "\r\n");
}
}
System.out.println(wenti);
System.out.println(daan);
}
else if (grade == 2) {
for (i = 1; i <= n; i++) {
int operator = (int) (Math.random() * 2);
if (operator == 0) {
int num1 = (int) (Math.random() * 10);
int num2 = (int) (Math.random() * 10);
result = num1 * num2;
wenti.append("(" + (i + 1) + ") " + num1 + " * " + num2 + "\r\n");
daan.append("(" + (i + 1) + ") " + num1 + " * " + num2 + " = " + result + "\r\n");
} else if (operator == 1) {
int x = (int) (Math.random() * 10);
int y = (int) (Math.random() * 10);
if (y == 0) {
System.out.println("除數不能为零");
}
if (x % y == 0) {
result = x / y;
wenti.append("(" + i + ") " + x + " / " + y + "\r\n");
daan.append("(" + i + ") " + x + " / " + y + " = " + result + "\r\n");
}
if (x % y != 0) {
result = x / y;
wenti.append("(" + i + ") " + x + " / " + y + "\r\n");
daan.append("(" + i + ") " + x + " / " + y + " = " + result + "..." + (x % y) + "\r\n");
}
}
}
System.out.println(wenti);
System.out.println(daan);
}
if (grade == 3) {
outLoop:for (i = 1; i <= n; i++) {
int OPNum = (rand.nextInt(3) + 2);
int S_num2 = (rand.nextInt(100) + 1);
S_wenti = S_num2 + "";
for (int j = 1; j <= OPNum; j++) {
int S_num = S_num2;
S_num2 = (rand.nextInt(1000) + 1);
int op = (rand.nextInt(4));
if (op == 0) {
if (S_num + S_num2 > 1000) {
j--;
continue;
}
} else if (op == 1) {
if (S_num - S_num2 < 0) {
j--;
continue;
}
} else if (op == 2) {
if (S_num1 * S_num2 > 10000) {
j--;
continue;
}
} else if (op == 3) {
if (S_num1 % S_num2 != 0 || S_num2 == 0) {
j--;
continue;
}
}
a = S_wenti + S_num1 + fuhao[op] + S_num2;
S_wenti += fuhao[op] + S_num2;
if (Integer.parseInt(answers(S_wenti))<0 || Integer.parseInt(answers(S_wenti))>100000) {
i--;
continue outLoop;
}
}
wenti.append("(" + i + ") " + S_wenti + "\r\n");
daan.append("(" + i + ") " + S_wenti + " = " + answers(S_wenti) + "\r\n");
//S_num1 = (rand.nextInt(1001));
//S_wenti = S_num1 + "";
}
System.out.println(wenti);
System.out.println(daan);
}
}
public static String answers(String S_wenti) {
Stack<String> number1 = new Stack<String>();
Stack<String> op_Stack = new Stack<String>();
String stc = S_wenti.replace(" ", "");
String number = "";
for (int i = 0; i < stc.length(); i++) {
char c = stc.charAt(i);
if (c >= '0' && c <= '9') {
number += c + "";
if (i + 1 >= stc.length()) {
number1.push(number);
number = "";
}
}
else {
if (!number.isEmpty()) {
number1.push(number);
number = "";
}
if (!op_Stack.empty() && comparePriority(c + "", op_Stack.peek()) < 1 ) {
while (!op_Stack.empty() && comparePriority(c + "", op_Stack.peek()) < 1) {
int a = Integer.parseInt(number1.pop());
int b = Integer.parseInt(number1.pop());
int d;
String stackTop = op_Stack.peek();
if (stackTop.equals("+")) {
d = b + a;
} else if (stackTop.equals("-")) {
d = b - a;
} else if (stackTop.equals("*")) {
d = b * a;
} else {
d = b / a;
}
number1.push(d + "");
stackTop = op_Stack.pop();
}
op_Stack.push(c + "");
}
else
op_Stack.push(c+"");
}
}
while (!op_Stack.empty()) {
String stackTop = op_Stack.pop();
int a = Integer.parseInt(number1.pop());
int b = Integer.parseInt(number1.pop());
int d;
if (stackTop.equals("+")) {
d = b + a;
} else if (stackTop.equals("-")) {
d = b - a;
} else if (stackTop.equals("*")) {
d = b * a;
} else {
d = b / a;
}
number1.push(d + "");
}
return number1.peek();
}
private static int comparePriority(String a, String b) {
if (a.equals(b)) {
return 0;
} else if (adv(a) > adv(b)) {
return 1;
} else if (adv(a) < adv(b)) {
return -1;
} else {
return 0;
}
}
private static int adv(String op) {
if (op.equals("*") || op.equals("/")) {
return 2;
} else if (op.equals("+") || op.equals("-")) {
return 1;
}
// if(op.equals("(")){
// return 0;
// }
return 0;
}
五、测试
第一组:10 3
输出结果:(1) 14 * 314 - 33
(2) 49 + 7 + 130 - 17 + 208
(3) 41 + 640 - 408
(4) 73 + 581 * 109
(5) 90 + 142 * 255 + 119 + 373
(6) 54 - 19 + 449 * 123
(7) 65 - 43 + 682 + 168 - 12
(8) 29 + 361 + 122
(9) 90 + 342 * 281 + 373 + 264
(10) 6 + 734 + 309
(1) 14 * 314 - 33 = 4363
(2) 49 + 7 + 130 - 17 + 208 = 377
(3) 41 + 640 - 408 = 273
(4) 73 + 581 * 109 = 63402
(5) 90 + 142 * 255 + 119 + 373 = 36792
(6) 54 - 19 + 449 * 123 = 55262
(7) 65 - 43 + 682 + 168 - 12 = 860
(8) 29 + 361 + 122 = 512
(9) 90 + 342 * 281 + 373 + 264 = 96829
(10) 6 + 734 + 309 = 1049
六、总结
本次作业的主要问题是没有认真学懂后缀表达式,出错的地方还有*/和后面的×÷没有匹配,所以找了很久问题都没有发现