2016012095+小学四则远算练习软件项目报告
小学四则运算联系项目报告
一、需求分析
二、功能设计
三、设计实现
四、算法详解
五、测试运行
六、总结
七、展示PSP
项目地址:https://git.coding.net/smallcard/libf.git
一、 需求分析
1、 编写目标:
数据范围100以内,无小数及负数,混合包含四种运算
2、 需求规定:
程序可接收一个输入参数n,然后随机产生n道加减乘除(分别使用符号+-*÷来表示)练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间。每个练习题至少要包含2种运算符。,练习题生成好后,将生成的n道练习题及其对应的正确答案输出到文件“result.txt”中。
二、功能设计
1.基本功能:实现四则混合运算的出题和计算
2.扩展功能(目前未加入):
(1)带括号的四则运算:已经实现了括号计算,未实现插入计算
(2)支持真分数的出题与运算:需注意分数可以自动化简(未完成)
3.流程图
三、设计实现
1、基本四则运算:
随机生成操作数,随机生成操作符所代表的数字,相应的在字符数组内 存储操作符,生成问题字符串后,采用中缀表达式转后缀表达式的形式计算结果并将结果加入问题数组中。
2、 设计函数:
1出题函数question();
2解题函数solvequestion();
四、算法详解
1、生成固定范围随机数
/*产生固定范围随机数*/ private static int rand(int min,int max){ return (int)(min)+(int)Math.round(Math.random()*(max-min)+min); }
2、判断优先级
+-为同一优先级,*/为同一优先级
/*判断优先级*/ private static int priority(char s){ switch (s) { case '+': return 1; case '-': return 1; case '*': return 2; case '÷': return 2; default: return -1; } }
3、进行固定数目的题目出具
随机产生操作符数量和种类存于数组中,将操作数和操作符拼接为字符串存放于问题汇总数组中
public static void question(String QuestionSum[],int Qnumber){ //Random rand=new Random(); int Tempnumber[]=new int[100]; String Tempoperator[]=new String[100]; for(int i=0;i<Qnumber;i++){ Tempnumber[0]=rand(1,100); int count=0; int ost=rand(3,5); for(int j=1;j<=ost;j++){ count++; int os=rand(0,3); switch(os){ case 0: Tempoperator[j]="+"; Tempnumber[j+1]=rand(2,100); break; case 1://判负* Tempoperator[j]="-"; Tempnumber[j+1]=rand(2,100); if(Tempnumber[j]<Tempnumber[j+1]){ int temp=Tempnumber[j]; Tempnumber[j]=Tempnumber[j+1]; Tempnumber[j+1]=temp; } break; case 2: if(Tempoperator[j-1]=="*"||Tempoperator[j-1]=="/"){ Tempoperator[j]="+"; Tempnumber[j+1]=rand(2,10); }else{ Tempoperator[j]="*"; Tempnumber[j+1]=rand(2,10); } break; case 3://整除* if(Tempoperator[j-1]=="*"||Tempoperator[j-1]=="÷"){ Tempoperator[j]="+"; Tempnumber[j+1]=rand(2,10); }else{ Tempoperator[j]="÷"; Tempnumber[j+1]=rand(2,10); Tempnumber[j]=Tempnumber[j+1]*rand(2,10); } break; } } String question=""+Tempnumber[0]; Tempoperator[1]="+"; for(int k=1;k<count;k++){ question+=Tempoperator[k]+Tempnumber[k+1]; } //System.out.println(question); int ans=solvequestion(question); if(ans>=0){ question = question + " = "+ans; }else{ String temp=makequestion(); question = question + " = "+solvequestion(temp); } //question="2*2+3+3+6÷2";//计算有误 //System.out.println(solvequestion(question)); QuestionSum[i]=question; } }
4、进行计算
(1)转后缀计算
采用操作数栈和操作符栈进行转化和计算
private static int solvequestion(String question){ char[] q; q=question.toCharArray(); int k=0; //System.out.println(q); Stack<Character> s=new Stack<Character>(); Stack<Integer> n=new Stack<Integer>(); for(int i=0;i<q.length;i++){ char temp=q[i]; if(q[i]=='0'&&!(Character.isDigit(q[i-1]))&&!(Character.isDigit(q[i+1]))){ k = k*10 + Integer.parseInt(String.valueOf(0)); n.push(k); } if(Character.isDigit(q[i])||q[i]=='0'){//数字进栈 k = k*10 + Integer.parseInt(String.valueOf(q[i])); if(i==q.length-1){ n.push(k); //System.out.println(k+"pp"); k=0; } }else{ if(k!=0){ n.push(k); //System.out.println(k+"oo"); k=0; } if(temp=='('){//左括号进栈 s.push(temp); }else if((temp == ')')){ while(s.peek()!='('){//左括号前出栈 int t=calculateSimple(s.pop(), n.pop(), n.pop()); n.push(t); } s.pop(); }else if(isType(temp)>0){ if(s.isEmpty()){ s.push(temp); //System.out.println(s.peek()+"++"); }else{ if(priority(temp)<= priority((s.peek()))){//优先级不大于栈顶 ,出栈后压入 //System.out.println(s.peek()); int t=calculateSimple(s.pop(), n.pop(), n.pop()); //System.out.println(t+"kk"); //System.out.println(s.peek()+"dd"); n.push(t); } s.push(temp); //System.out.println(s.peek()+"--"); } } } } if(k!=0){ n.push(k); } while(!s.empty()&&n.size()>=2){ int t=calculateSimple(s.pop(), n.pop(), n.pop()); //System.out.println(t+"=="); n.push(t); }//压入 //s.push('0'); //System.out.println(s.pop()); return n.pop(); }
(2)单项计算
private static int calculateSimple(char operator, int a, int b) { int result = 0; switch (operator) { case '+': result = a + b; break; case '-': result = b - a; break; case '*': result = a * b; break; case '÷': if(a==0) break; else{ result = b / a; break; } } return result; }
5、输出到文件
public static void printfile(String[]QuestionSum,int Qnumber)throws IOException{ FileOutputStream fs = new FileOutputStream(new File("../text.txt")); PrintStream p = new PrintStream(fs); p.println("2016012095"); for(int i=0;i<Qnumber;i++){ p.println(QuestionSum[i]); System.out.println(QuestionSum[i]); } p.close(); }
五、测试运行
六、总结
1、在项目实现方面,没有实现附加功能,后期会继续改进
2、项目所需时间远远比所计划的长,在进行设计分析的时候考虑不周。
3、进行模块化的软件功能实现,在开发过程中免去了很多繁琐的细节链接,增加了代码可移植性和可读性,受益良多
七、展示PSP
PSP |
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
10 |
8 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
10 |
8 |
Development |
开发 |
200 |
467 |
Analysis |
需求分析 (包括学习新技术) |
10 |
12 |
Design Spec |
生成设计文档 |
0 |
0 |
Design Review |
设计复审 (和同事审核设计文档) |
0 |
0 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
10 |
15 |
Design |
具体设计 |
30 |
40 |
Coding |
具体编码 |
200 |
360 |
Code Review |
代码复审 |
30 |
30 |
Test |
测试(自我测试,修改代码,提交修改) |
10 |
10 |
Reporting |
报告 |
140 |
140 |
Test Report |
测试报告 |
60 |
60 |
Size Measurement |
计算工作量 |
40 |
30 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
40 |
50 |