第三次作业

第二次作业: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

六、总结

本次作业的主要问题是没有认真学懂后缀表达式,出错的地方还有*/和后面的×÷没有匹配,所以找了很久问题都没有发现

posted @ 2018-09-19 11:49  刘刘刘刘华强呀  阅读(149)  评论(1编辑  收藏  举报