任务1源码可直接克隆的仓库地址:https://coding.net/u/dengqq/p/homework/git
一、需求分析:
l 随机产生n道加减乘除练习题
l 数字在0到100之间,运算符在3到5个之间
l 至少包含2种运算符,不出现负数和非整数
二、功能设计:
基本功能:
1) 可接收一个输入参数n, 随机产生n道加减乘除(分别使用符号+-*÷来表示)练习题
2) 数字在0到100之间,运算符在3个到5个之间,至少包含2种运算符,不出现负数和非整数
3) 将生成的n道练习题及其对应的正确答案输出到文件“result.txt”中
扩展功能:
1) 支持有括号的运算式
2) 支持真分数的出题与运算
三、设计实现
类:
1) java.util.Scanner 功能:获取控制台输入(输入n)
2) java.util.Random 功能:产生随机数
3) java.util.ArrayList 功能:需要用到数组
4) java.util.Stack 功能:需要用栈将中缀表达式转成后缀表达式
5) java.util.regex.Pattern 功能:需要使用正则表达式匹配数字
关系:这几个类之间具有关联关系
函数:
1) InfixToSuffix 功能:将中缀表达式转化成后缀表达式
2) suffixToArithmetic 功能:通过后缀表达式求出运算结果
3) calculate 功能:加减乘除的运算
4) stringToArithmetic 功能:给出中缀表达式能求出运算结果
5) 主函数
流程图:
逻辑关系:如上述流程图
1) suffixToArithmetic函数调用了caculate函数通过后缀表达式求到运算结果
2) stringToArithmetic函数调用了InfixToSuffix函数和suffixToArithmetic函数由中缀表达式求出结果
3) 主函数通过调用stringToArithmetic函数将随机生成的前缀表达式求出运算结果
四、算法详解
生成题目:利用for循环,间隔生成数字和运算符
public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输入n"); int amount = sc.nextInt(); char[] operator=new char[]{‘+‘,‘-‘,‘*‘,‘/‘}; for(int i=0;i<amount;i++){ int max=100; int min=0; Random random = new Random(); ArrayList<String> expression=new ArrayList<String>(); int number=random.nextInt(6)%(6-4+1)+4; //产生0到100的随机数 String sr=new String(); for(int j=0;j<number-2;j++){ int s = random.nextInt(max)%(max-min+1) + min; System.out.print(s); String y = Integer.toString(s); String m=new String(); sr+=y; int t=random.nextInt(4);//产生4个随机的运算符 m=String.valueOf(operator[t]); sr+=m; System.out.print(m); } int p = random.nextInt(100)%(101); String x = Integer.toString(p); sr+=x; System.out.print(p);
处理运算符的优先级:
public static String infixToSuffix(String infix) { Stack<Character> stack = new Stack<Character>(); String suffix = ""; int length = infix.length(); for (int i = 0; i < length; i++) { Character temp; char c = infix.charAt(i); switch (c) { case ‘ ‘: break; case ‘+‘: case ‘-‘: while (stack.size() != 0) { temp = stack.pop(); suffix += " " + temp; } stack.push(c); suffix += " "; break; case ‘*‘: case ‘/‘: while (stack.size() != 0) { temp = stack.pop(); if(temp==‘+‘||temp==‘-‘){ stack.push(temp); break; } else { suffix += " " + temp; } } stack.push(c); suffix += " "; break; //如果是数字,直接存入 default: suffix += c; } }
解答题目:
for (int i = 0; i < strings.length; i++) strings[i].trim(); Stack<Double> stack = new Stack<Double>(); for (int i = 0; i < strings.length; i++) { if (strings[i].equals("")) continue; if ((pattern.matcher(strings[i])).matches()) { stack.push(Double.parseDouble(strings[i])); } else { double y = stack.pop(); double x = stack.pop(); double d= 0; stack.push(caculate(x, y, strings[i])); } return stack.pop();
五、测试运行
六、 满意的代码
这段代码虽然不难,但是很简单,看起来比较明了。
private static double caculate(double x, double y, String simble) { if (simble.trim().equals("+")) return x + y; if (simble.trim().equals("-")) return x - y; if (simble.trim().equals("*")) return x * y; if (simble.trim().equals("/")) return x / y; return 0; }
七、 总结
因为之前对Java不够熟悉,经验不足,所以很多编程的方法都不知道,很多代码都是一边学一边写,浪费了很多时间。代码的整洁很重要,由于我的代码太乱,有些代码可能是多余的,导致在修改代码的时候特别不方便,遇到问题的时候经常无从下手。时间的规划也很重要,这次作业由于没能合理地分配时间,导致时间不够用。在这次作业中,遇到了很多问题,虽然有一部分问题由于自身编程能力太低并没有解决,但是经过一周的学习,学到了很多,对Java明显比之前更熟悉。
八、 展示PSP
PSP |
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
10 |
5 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
10 |
15 |
Development |
开发 |
360 |
500 |
Analysis |
需求分析 (包括学习新技术) |
120 |
180 |
Design Spec |
生成设计文档 |
10 |
20 |
Design Review |
设计复审 |
5 |
3 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
5 |
10 |
Design |
具体设计 |
30 |
30 |
Coding |
具体编码 |
90 |
120 |
Code Review |
代码复审 |
10 |
20 |
Test |
测试(自我测试,修改代码,提交修改) |
20 |
30 |
Reporting |
报告 |
120 |
150 |
Test Report |
测试报告 |
10 |
10 |
Size Measurement |
计算工作量 |
5 |
5 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
30 |
20 |