一、项目Github地址
https://github.com/LilyFuEnLi/Arithmetic_SE
(注:附上coding.net项目网址:https://git.coding.net/LilyF/Software.git,coding.net与GitHub功能相同,coding.net的语言为中文,而GitHub是英文。)
二、项目报告
1、需求分析
(1)程序可接收一个输入参数n,然后随机产生n道加减乘除练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间,即运算数字在4~6个之间。
(2)为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符。同时,由于小学生没有分数与负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3/5+2=2.6,2-5+10=7等算式。
(3)练习题生成好后,将自己的学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中,不要输出额外信息,文件目录与程序目录一致。
(4)当程序接收的参数为5时,即产生5个运算式,以下为我试验中输出的文件,第一行为我的学号。
201571030108 (44*66)+(67-54)=2917 (43+54)-22*(37-37)=97 (74+35)*63+(17-17)=6867 (58+54)-(18+54)=50 (24+65)-(9+50)=30 |
(5)附加功能:支持有括号的运算式,包括出题与求解正确答案。由于随机产生的运算数字为4~6个,所以算式中存在的括号设置为2个。
2、功能设计
(1)屏幕打印提示输入需要产生的运算式个数number。
(2) 生成一个包含4~6个数字,3~5个运算符且包含两个括号的字符串表达式。
(3)屏幕依次显示number个运算式,要求学生解答,并显示答题是否正确。
(5)计算出表达式的结果,并且运算过程中不能出现负数。
(4)统计学生答题情况,计算并显示学生的正确率。
(5)最后将运算表达式和计算结果写入result.txt文件,提示学生进行查询并复习。
3、设计实现
目含有两个java文件,分别是Main.java与Calculate_SE .java,Calculate_SE .java中包含calaulate_AE(产生随机运算式)、transferToPostfix(中缀表达式转化为逆波兰式)、calculate(计算逆波兰式)等方法,Main调用Calculate_SE中的各个方法完成项目,设计流程图如图1所示。
图 1 设计流程图
4、测试运行
运行Main.java文件,输入产生运算式个数number为5,依次进行答题(如图2所示),同时生成result.txt文件,如图3所示,cmd运行文件run.bat文件截图如图4所示。
图2 图3
图 4
5、核心代码
(1)生成随机运算式,调用方法计算结果
1 public void calaulate_AE(int number) { 2 int Right=0; 3 float R = 0; 4 int F=0; 5 while(F==0) 6 { 7 for(int i=0;i<number;i++) 8 { 9 CN[i]=(int)(Math.random()*2+4); 10 int Bracket=(int)(Math.random()*CN[i]-2); 11 for(int j=0;j<CN[i];j++) 12 { 13 N[i][j]=(int) (Math.random()*100+1); 14 } 15 for(int k=0;k<CN[i]-1;k++) 16 { 17 C[i][k]=Str[(int)(Math.random()*3)]; 18 } 19 for(int k=0;k<CN[i]-1;k++) 20 { 21 while(C[i][0]==C[i][1]) 22 C[i][1]=Str[(int)(Math.random()*3)]; 23 if(C[i][k]=='-' && (N[i][k]<N[i][k+1])) 24 { 25 int temp=0; 26 temp=N[i][k]; 27 N[i][k+1]=temp; 28 N[i][k]=temp; 29 } 30 if(C[i][k]=='/' && (N[i][k]%N[i][k+1]!=0)) 31 { 32 int temp=N[i][k]; 33 N[i][k] = N[i][k] <N[i][k+1]? N[i][k]: N[i][k+1]; 34 N[i][k+1] = temp > N[i][k+1]? temp: N[i][k+1]; 35 for(int num = N[i][k]; num >= 1; num--) 36 { 37 if(N[i][k] % num == 0 && N[i][k+1] % num == 0) 38 { 39 N[i][k+1]=num; 40 break; 41 } 42 } 43 } 44 } 45 String AE=new String(); 46 LinkedList<String> list=new LinkedList<>(); 47 list.add(String.valueOf('(')); 48 list.add(String.valueOf(N[i][0])); 49 list.add(String.valueOf(C[i][0])); 50 list.add(String.valueOf(N[i][1])); 51 list.add(String.valueOf(')')); 52 list.add(String.valueOf(C[i][1])); 53 AE+='('+String.valueOf(N[i][0])+String.valueOf(C[i][0])+String.valueOf(N[i][1])+')'+String.valueOf(C[i][1]); 54 for(int j=2;j<CN[i]-2;j++) 55 { 56 list.add(String.valueOf(N[i][j])); 57 list.add(String.valueOf(C[i][j])); 58 AE+=String.valueOf(N[i][j])+String.valueOf(C[i][j]); 59 } 60 list.add(String.valueOf('(')); 61 list.add(String.valueOf(N[i][CN[i]-2])); 62 list.add(String.valueOf(C[i][CN[i]-2])); 63 list.add(String.valueOf(N[i][CN[i]-1])); 64 list.add(String.valueOf(')')); 65 AE+='('+String.valueOf(N[i][CN[i]-2])+String.valueOf(C[i][CN[i]-2])+String.valueOf(N[i][CN[i]-1])+')'+'='; 66 String sum=transferToPostfix(list); 67 char fir =sum.charAt(0); 68 if(fir=='-') 69 F=0; 70 else 71 F=1; 72 System.out.print(AE); 73 String SUM=scanner.nextLine(); 74 if(SUM.equals(sum)) 75 { 76 System.out.print("回答真确,Very Good!(*^▽^*):\n"); 77 Right++; 78 } 79 else 80 System.out.print("回答错误,要加油哦!(*^▽^*):\n"); 81 float R1 = (float)Right; 82 float R2 = (float)number; 83 R=(float) (R1/R2*100.00); 84 AE+=sum; 85 Arithmetic.add(AE); 86 } 87 System.out.print("本次答题共计"+number+"道,回答正确"+Right+"道,正确率为"+R+"%.\n"); 88 } 89 }
(2)中缀表达式转为后缀表达式
private static String transferToPostfix(LinkedList<String> list){ Iterator<String> it=list.iterator(); while (it.hasNext()) { String s = it.next(); if (isOperator(s)) { if (operators.isEmpty()) { operators.push(s); } else {//如果读入的操作符为非")"且优先级比栈顶元素的优先级高或一样,则将操作符压入栈 if (priority(operators.peek())<=priority(s)&&!s.equals(")")) { operators.push(s); } else if(!s.equals(")")&&priority(operators.peek())>priority(s)) { while (operators.size()!=0&&priority(operators.peek())>=priority(s)&&!operators.peek().equals("(")) { if (!operators.peek().equals("(")) { String operator=operators.pop(); sb.append(operator).append(" "); output.push(operator); } } operators.push(s); } //如果读入的操作符是")",则弹出从栈顶开始第一个"("及其之前的所有操作符 else if (s.equals(")")) { while (!operators.peek().equals("(")) { String operator=operators.pop(); sb.append(operator).append(" "); output.push(operator); } //弹出"(" operators.pop(); } } } //读入的为非操作符 else { sb.append(s).append(" "); output.push(s); } } if (!operators.isEmpty()) { Iterator<String> iterator=operators.iterator(); while (iterator.hasNext()) { String operator=iterator.next(); sb.append(operator).append(" "); output.push(operator); iterator.remove(); } } String sum= calculate(); return sum; }
(3)根据后缀表达式计算结果
private static String calculate(){ LinkedList<String> mList=new LinkedList<>(); String[] postStr=sb.toString().split(" "); for (String s:postStr) { if (isOperator(s)) { if (!mList.isEmpty()) { int num1=Integer.valueOf(mList.pop()); int num2=Integer.valueOf(mList.pop()); int newNum=cal(num2,num1,s); mList.push(String.valueOf(newNum)); } } else { //数字则压入栈中 mList.push(s); } } if (!mList.isEmpty()) { return mList.pop(); } return null; }
6、总结
在本次项目中,我建立了两个java文件,分别是Main.java与Calculate_SE .java,Calculate_SE .java用于整体的方法实现,其中包含calaulate_AE(产生随机运算式)、transferToPostfix(中缀表达式转化为逆波兰式)、calculate(计算逆波兰式)等方法,然后利用Main调用Calculate_SE中的各个方法完成整体项目。实现小学生四则运算练习软件的设计,加入了附加功能(括号运算),但未能实现分数运算,后期我会继续学习改进,使其功能较为完善。
7、展示PSP
PSP2.1 | 任务内容 | 计划完成的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
PLanning | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 30 | 40 |
Developmet | 开发 | 240 | 360 |
Analysis | 需求分析(包括学习新技术) | 30 | 30 |
Design Spec | 生成设计文档 | 10 | 15 |
Design Revie | 设计复审(和同事审核设计文档) | 15 | 15 |
Coding Standard | 代码规范 | 10 | 20 |
Design | 具体设计 | 30 | 45 |
Coding | 具体编码 | 120 | 240 |
Code Review | 代码复审 | 10 | 10 |
Test | 测试(自我测试,修改代码,提交修改) | 20 | 30 |
Reporting | 报告 | 30 | 40 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 5 | 5 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改机计划 | 10 | 15 |
8、项目心得
首先,感受到每个项目的分析阶段特别重要,你的分析缺陷大就意味着你返工的可能性越大。当你对于一个项目的整体思路把握较好后,代码编程时会流畅许多,所以我们一定要养成一个良好的开发习惯。其次,本次项目过程中,感觉特别对不起Java老师,好久没有练习java语言,生疏了许多。这应该就是那句“学如逆水行舟,不进则退”吧。