- 为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符。同时,由于小学生没有分数与负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3/5+2=2.6,2-5+10=7等算式。
- 练习题生成好后,将你的学号
- 当程序接收的参数为4时,以下为输出文件示例。
2、功能分析
- 使用Java中提供的Random类,随机产生0-100的正整数,并与随机产生的四则运算符号相结合,构成随机的四则运算。
- 由于小学并没有接触到负整数,故随机计算结果为负的除去。
- 当产生符合要求的四则运算题目时,计算正确答案并输出到名为result.txt的文件中。
3、设计实现
4、测试运行
5、核心代码
- 随机生成四则运算表达式:
1 int[] number_temp = new int[rand.nextInt(2)+3]; 2 String[] str_temp = new String[number_temp.length-1]; 3 for(int i=0;i<number_temp.length;i++) 4 { 5 if(i<number_temp.length-1) 6 { 7 number_temp[i]=rand.nextInt(100); 8 list_temp.add(String.valueOf(number_temp[i])); 9 str_temp[i]=operator[rand.nextInt(4)]; 10 list_temp.add(str_temp[i]); 11 12 } 13 else 14 { 15 number_temp[i]=rand.nextInt(100); 16 list_temp.add(String.valueOf(number_temp[i])); 17 } 18 }
- 用调度场算法产生逆波兰式:
public static ArrayList<String> produce_RPN(ArrayList<String> list_temp) { int t=0,i=0; String tmp; Tack mytack = new Tack(20); ArrayList<String> lt_temp = new ArrayList<String>(); while(true) { tmp = list_temp.get(i++); if(isInteger(tmp)) { lt_temp.add(tmp); } else{ if(mytack.myisempty()) { mytack.mypush(tmp); } else{ if(isCPriority(tmp, mytack.mypeek())) mytack.mypush(tmp); else{ lt_temp.add(mytack.mypop()); mytack.mypush(tmp); } } } if(i>=list_temp.size()) { while(!mytack.myisempty()) lt_temp.add(mytack.mypop()); System.out.println(transform_string(list_temp)); list_temp = lt_temp; System.out.println(list_temp); return list_temp; } } }
- 用逆波兰式,计算表达式的结果:
public static int calculate_RPN(ArrayList<String> list_temp) { int i=0,t; double a=0,b=0; String l_temp; Stack sk=new Stack(20); for(t=0;t<list_temp.size();t++) { l_temp = list_temp.get(i++); if(!isInteger(l_temp)) { b = sk.mypop(); a = sk.mypop(); switch(l_temp) { case "+":sk.mypush(a+b);break; case "-":sk.mypush(a-b);break; case "*":sk.mypush(a*b);break; case "/": if(b==0) return -1; sk.mypush(a/b);break; } System.out.println("st.mytop: "+sk.mypeek()); } else{ sk.mypush((double)Integer.parseInt(l_temp)); } } if(!sk.myisempty()) { a = sk.mypop(); b = a-(int)a; System.out.println("a: "+a); if(a>0 && b==0 ) { return (int)a; } else return -1; } else return -1; }
- 当计算结果为正整数时,添加到数组list。反之则重复上述步骤:
count=calculate_RPN(produce_RPN(list_temp)); if(count !=-1) { list_temp.add(" = "+count); list.add(transform_string(list_temp)); number_n--; list_temp.clear(); } else list_temp.clear();
- 当产生适当符合要求的表达式时,现将自己的学号、姓名写到result.txt文件中,再将产生的表达式写到result.txt文件中:
try { outSTr = new FileOutputStream(file1); Buff = new BufferedOutputStream(outSTr); try { Buff.write("201571030104 丁炜轩".getBytes()); Buff.write(" ".getBytes()); } catch (IOException e) { e.printStackTrace(); } for (int i = 0; i < list.size(); i++) { try { Buff.write(list.get(i).getBytes()); Buff.write(" ".getBytes()); } catch (IOException e) { e.printStackTrace(); i--; } } Buff.flush(); Buff.close(); } catch (IOException e) { e.printStackTrace(); } //Buff.close(); try { outSTr.close(); } catch (IOException e) { e.printStackTrace(); } for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i)); System.out.println(); } System.out.print("计算完毕!");
- 到这时候,result.txt文件中已经就有了我们需要的四则运算表达式,以及正确的结果。
- 还有几个小的函数,这里简单说一下:
- 1.判断字符串是否为正整数:
public static boolean isInteger(String str) { for (int i = str.length();--i>=0;){ if (!Character.isDigit(str.charAt(i))){ return false; } } return true; }
- 2.判断运算符号的优先级顺序:
public static boolean isCPriority(String str,String s) { if((str+s).equals("*+") || (str+s).equals("*-") || (str+s).equals("/+") || (str+s).equals("/-")) return true; else return false; }
- 3.将动态数组转换为字符串类型:
public static String transform_string(ArrayList<String> list_temp) { String s=""; for(int i=0;i<list_temp.size();i++) { s+=list_temp.get(i); } return s; }
- 在本次实验中,重要用到了栈:
-
static class Stack { int mytop; double stk[]; public Stack(int num) { mytop=-1; stk=new double[num]; } /*出栈*/ double mypop() { double peek=stk[mytop]; mytop--; return peek; } /*入栈*/ void mypush(double x) { mytop++; stk[mytop]=x; } /*判空*/ Boolean myisempty() { if(mytop==-1) return true; else return false; } /*取栈顶元素*/ double mypeek() { double peek=stk[mytop]; return peek; } /*栈大小*/ int mysize() { return mytop+1; } } static class Tack { int mytop; String tk[]; public Tack(int num) { mytop=-1; tk=new String[num]; } /*出栈*/ String mypop() { String peek=tk[mytop]; mytop--; return peek; } /*入栈*/ void mypush(String x) { mytop++; tk[mytop]=x; } /*判空*/ Boolean myisempty() { if(mytop==-1) return true; else return false; } /*取栈顶元素*/ String mypeek() { String peek=tk[mytop]; return peek; } /*栈大小*/ int mysize() { return mytop+1; } }
6、总结
在本次实验中,主要在代码完成、调试中花了很多时间。我感觉一方面由于长时间不使用Java语言编写程序,对于Java语法结构、类的定义、函数的构造等知识方面都严重匮乏。一方面还是对于软件工程这门课理解略有偏差。不过在老师,以及助教老师的共同帮助下,我学到了一些书本上学不到的知识。值此,由衷的感谢老师们对于我的鼓励、帮助、以及肯定,我会继续发挥自己的长处,弥补自己不足的地方,为了祖国美好的明天,让我们共同努力!
PSP2.1 |
任务内容 |
计划完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
30 |
46 |
· Estimate |
· 估计这个任务需要多少时间,并规划大致工作步骤 |
30 |
46 |
Development |
开发 |
160 |
200 |
·· Analysis |
需求分析 (包括学习新技术) |
20 |
20 |
· Design Spec |
· 生成设计文档 |
15 |
20 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
5 |
10 |
· Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
20 |
20 |
· Design |
具体设计 |
30 |
30 |
· Coding |
具体编码 |
60 |
80 |
· Code Review |
· 代码复审 |
5 |
10 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
5 |
10 |
Reporting |
报告 |
60 |
80 |
·· Test Report |
· 测试报告 |
30 |
40 |
· Size Measurement |
计算工作量 |
15 |
20 |
· Postmortem & Process Improvement Plan |
· 事后总结 ,并提出过程改进计划 |
15 |
20 |