源码在Github的仓库主页链接地址:https://github.com/rucr9/rucr
看到这个题目,大概很多人会发出“切,这也太简单了吧!有必要小题大做?”的感叹!是的,仅仅作为一道数学运算是没难度,但是,如何实现智能出题并计算正确答案,为大脑减压呢?接下来,我将用java编写程序实现小学四则运算。
需求分析
1.程序可接收一个输入参数n,然后随机产生n道加减乘除练习题;
2.每个数字在 0 和 100 之间,运算符在3个到5个之间;
3.所出的练习题在运算过程中不得出现负数与非整数;
4.将练习题和计算结果一起输出到文件中;
5.当程序接收的参数为4时,以下为输出文件示例:
功能设计
用户输入需要出题的数量n,然后随机产生n道加减乘除练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间,并且所出的练习题在运算过程中不得出现负数与非整数;最后将练习题和运算结果输出到result.txt文件中。
设计实现
1.类
主类:Arithmetic,这个类主要是用户输入出题的数量,随机产生练习题,并调用Expression类中的方法计算结果,最后输出到result.txt文件中。
运算类:Calculate,此类规定了运算符的优先级和计算规则。
逆波兰式转换类:Expression,此类负责将中序表达式转换为右序表达式,并调用Calculate中的方法求值。
栈类:Stack,此类定义栈方法。
2.程序执行流程
测试运行
核心代码
Arithmetic类
1 public static ArrayList ss = new ArrayList();2
3 public static void main(String[] args) throwsException {4
5 System.out.println("Input a number:");6 int count = newScanner(System.in).nextInt();7 File file =new File("./result.txt");8 FileOutputStream fops=null;9
10 try{11 fops = newFileOutputStream(file);12
13 } catch(FileNotFoundException e) {14 e.printStackTrace();15 }16 PrintStream ps= newPrintStream(fops);17 ps.println("201571030125");18 boolean f = true;19 for (int i=0;i
34
35 //随机产生算式
36 public staticString Data()37 {38 Random rand =newRandom();39 ArrayList numlist = new ArrayList();40 ArrayList express = new ArrayList();41 //产生随机数
42 for(int i&#61;0;i<5;i&#43;&#43;)43 {44 numlist.add(rand.nextInt(100)&#43;1);45 }46 //System.out.print(numlist);
47 String[] operator&#61;new String[]{"&#43;","-","*","/"};48 int size&#61;numlist.size();49 String[] num&#61;newString[size];50 for(int i&#61;0;i
60
61 for(int i&#61;0;i
Calulate类
1 //判断是否为操作符号
2 public static booleanisOperator(String operator) {3 if (operator.equals("&#43;") || operator.equals("-")4 || operator.equals("*") || operator.equals("/")5 || operator.equals("(") || operator.equals(")"))6 return true;7 else
8 return false;9 }10 //设置操作符号的优先级别
11 public static intpriority(String operator) {12 if (operator.equals("&#43;") || operator.equals("-"))13 return 1;14 else if (operator.equals("*") || operator.equals("/"))15 return 2;16 else
17 return 0;18 }19 //做2值之间的计算
20 public staticString twoResult(String operator, String a, String b) {21 try{22 String op &#61;operator;23 String rs &#61; newString();24 double x &#61;Double.parseDouble(b);25 double y &#61;Double.parseDouble(a);26 boolean f &#61; true;27
28 double z &#61; 0.0;29 if (op.equals("&#43;"))30 z &#61; x &#43;y;31 else if (op.equals("-"))32 z &#61; x -y;33 else if (op.equals("*"))34 z &#61; x *y;35 else if (op.equals("/"))36 {37 if(y&#61;&#61;0) {38 y&#61;1;39 z&#61;999999;40 }41 z &#61; x /y;42 if(z*y!&#61;x) z&#61;999999;43 }44 else
45 z &#61; 999999;46 if(z<0) z&#61;999999;47 if(z!&#61;(int)z) z&#61;999999;48 returnString.valueOf(z);49 } catch(NumberFormatException e) {50 System.out.println("input has something wrong!");51 return "Error";52 }53 }
逆波兰式转换方法
1 private voidtoRight() {2 Stack aStack &#61; newStack();3 String operator;4 int position &#61; 0;5 while (true) {6 if(Calculate.isOperator((String) expression.get(position))) {7 if (aStack.top &#61;&#61; -1
8 || ((String) expression.get(position)).equals("(")) {9 aStack.push(expression.get(position));10 } else{11 if (((String) expression.get(position)).equals(")")) {12 while(true){13 if (aStack.top !&#61; -1&&!((String) aStack.top()).equals("(")) {14 operator &#61;(String) aStack.pop();15 right.add(operator);16 }else{17 if(aStack.top !&#61; -1)18 aStack.pop();19 break;20 }21 }22 } else{23 while(true){24 if (aStack.top !&#61; -1&&Calculate.priority((String) expression25 .get(position)) <&#61;Calculate26 .priority((String) aStack.top())27 ) {28 operator &#61;(String) aStack.pop();29 if (!operator.equals("("))30 right.add(operator);31 }else{32 break;33 }34
35 }36 aStack.push(expression.get(position));37 }38 }39 } else
40 right.add(expression.get(position));41 position&#43;&#43;;42 if (position >&#61;expression.size())43 break;44 }45 while (aStack.top !&#61; -1) {46 operator &#61;(String) aStack.pop();47 if(!operator.equals("("))48 right.add(operator);49 }50 }
逆波兰式求值方法
1 booleangetResult() {2
3
4 this.toRight();5
6 Stack aStack &#61; newStack();7 String op1, op2, is &#61; null;8 String temp&#61;"";9 Iterator it &#61;right.iterator();10 while(it.hasNext()) {11 is &#61;(String) it.next();12 if(Calculate.isOperator(is)) {13 op1 &#61;(String) aStack.pop();14 op2 &#61;(String) aStack.pop();15 temp &#61;Calculate.twoResult(is, op1, op2);16 double td &#61;Double.parseDouble(temp.trim());17 if(td&#61;&#61;999999.0){18 return false;19
20 }21 aStack.push(temp);22 } else
23 aStack.push(is);24 }25 expresult &#61;(String) aStack.pop();26
27 it &#61;expression.iterator();28 while(it.hasNext()) {29 String tempstr &#61;(String) it.next();30 System.out.print(tempstr);31
32 }33 System.out.println("&#61;" &#43;expresult);34 return true;35
36 }
总结
此项目看似简单&#xff0c;但实际上要考虑的问题有很多&#xff0c;比如如何产生随机数&#xff0c;随机数和运算符如何结合&#xff0c;用什么结构存储数据&#xff0c;使用什么方法计算表达式(正则表达式&#xff0c;逆波兰式等等)&#xff0c;如何去除不符合要求的运算式&#xff0c;如何处理异常等等。
起初看到题目时&#xff0c;感觉这不就是加减乘除运算嘛&#xff0c;有什么难的。但是&#xff0c;当具体设计的时候发现困难重重&#xff0c;必须思路清晰&#xff0c;逻辑缜密&#xff0c;写代码时才不会东一下西一下&#xff0c;最后一团乱&#xff0c;连自己都搞不明白自己在干嘛了&#xff0c;所以&#xff0c;拿到任何一个题目时都不要急于写代码&#xff0c;做好需求分析、设计实现等前期工作是非常重要的。
最后&#xff0c;提醒各位园友养成编辑过程中随时保存博客的习惯&#xff0c;以防手一抖、头脑一发昏刷新网页或者关闭浏览器&#xff0c;这可真的是前功尽弃啊&#xff01;痛到欲哭无泪。。。本人就是犯了这样的错误&#xff0c;导致重写博客&#xff01;&#xff01;&#xff01;
存在的问题
1.最后的计算结果都带有小数点&#xff1b;
2.java自带了栈类&#xff0c;我在这里重新定义有些多余&#xff1b;
3.产生的练习题都是5个运算数。
本项目参考逆波兰式算法http://blog.csdn.net/yunxiang/article/details/1918717&#xff0c;并根据需求和自己的理解进行改进而成&#xff0c;如有好的建议&#xff0c;请多多指教&#xff01;我将非常感谢&#xff01;
PSP
PSP2.1
任务内容
计划完成需要的时间(min)
实际完成需要的时间(min)
Planning
计划
15
20
Estimate
估计这个任务需要多少时间&#xff0c;并规划大致工作步骤
20
25
Development
开发
120
180
Analysis
需求分析 (包括学习新技术)
15
10
Design Spec
生成设计文档
10
8
Design Review
设计复审 (和同事审核设计文档)
15
20
Coding Standard
代码规范 (为目前的开发制定合适的规范)
20
25
Design
具体设计
30
35
Coding
具体编码
180
240
Code Review
代码复审
15
20
Test
测试(自我测试&#xff0c;修改代码&#xff0c;提交修改)
20
25
Reporting
报告
20
22
Test Report
测试报告
5
5
Size Measurement
计算工作量
5
10
Postmortem & Process Improvement Plan
事后总结 ,并提出过程改进计划
8
10