看到这个题目,大概很多人会发出“切,这也太简单了吧!有必要小题大做?”的感叹!是的,仅仅作为一道数学运算是没难度,但是,如何实现智能出题并计算正确答案,为大脑减压呢?接下来,我将用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=0;i<5;i++)43 {44 numlist.add(rand.nextInt(100)+1);45 }46 //System.out.print(numlist);
47 String[] operator=new String[]{"+","-","*","/"};48 int size=numlist.size();49 String[] num=newString[size];50 for(int i=0;i
60
61 for(int i=0;i
Calulate类
1 //判断是否为操作符号
2 public static booleanisOperator(String operator) {3 if (operator.equals("+") || 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("+") || 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 =operator;23 String rs = newString();24 double x =Double.parseDouble(b);25 double y =Double.parseDouble(a);26 boolean f = true;27
28 double z = 0.0;29 if (op.equals("+"))30 z = x +y;31 else if (op.equals("-"))32 z = x -y;33 else if (op.equals("*"))34 z = x *y;35 else if (op.equals("/"))36 {37 if(y==0) {38 y=1;39 z=999999;40 }41 z = x /y;42 if(z*y!=x) z=999999;43 }44 else
45 z = 999999;46 if(z<0) z=999999;47 if(z!=(int)z) z=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 = newStack();3 String operator;4 int position = 0;5 while (true) {6 if(Calculate.isOperator((String) expression.get(position))) {7 if (aStack.top == -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 != -1&&!((String) aStack.top()).equals("(")) {14 operator =(String) aStack.pop();15 right.add(operator);16 }else{17 if(aStack.top != -1)18 aStack.pop();19 break;20 }21 }22 } else{23 while(true){24 if (aStack.top != -1&&Calculate.priority((String) expression25 .get(position)) <=Calculate26 .priority((String) aStack.top())27 ) {28 operator =(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++;42 if (position >=expression.size())43 break;44 }45 while (aStack.top != -1) {46 operator =(String) aStack.pop();47 if(!operator.equals("("))48 right.add(operator);49 }50 }
逆波兰式求值方法
1 booleangetResult() {2
3
4 this.toRight();5
6 Stack aStack = newStack();7 String op1, op2, is = null;8 String temp="";9 Iterator it =right.iterator();10 while(it.hasNext()) {11 is =(String) it.next();12 if(Calculate.isOperator(is)) {13 op1 =(String) aStack.pop();14 op2 =(String) aStack.pop();15 temp =Calculate.twoResult(is, op1, op2);16 double td =Double.parseDouble(temp.trim());17 if(td==999999.0){18 return false;19
20 }21 aStack.push(temp);22 } else
23 aStack.push(is);24 }25 expresult =(String) aStack.pop();26
27 it =expression.iterator();28 while(it.hasNext()) {29 String tempstr =(String) it.next();30 System.out.print(tempstr);31
32 }33 System.out.println("=" +expresult);34 return true;35
36 }
总结
此项目看似简单,但实际上要考虑的问题有很多,比如如何产生随机数,随机数和运算符如何结合,用什么结构存储数据,使用什么方法计算表达式(正则表达式,逆波兰式等等),如何去除不符合要求的运算式,如何处理异常等等。
起初看到题目时,感觉这不就是加减乘除运算嘛,有什么难的。但是,当具体设计的时候发现困难重重,必须思路清晰,逻辑缜密,写代码时才不会东一下西一下,最后一团乱,连自己都搞不明白自己在干嘛了,所以,拿到任何一个题目时都不要急于写代码,做好需求分析、设计实现等前期工作是非常重要的。
最后,提醒各位园友养成编辑过程中随时保存博客的习惯,以防手一抖、头脑一发昏刷新网页或者关闭浏览器,这可真的是前功尽弃啊!痛到欲哭无泪。。。本人就是犯了这样的错误,导致重写博客!!!
存在的问题
1.最后的计算结果都带有小数点;
2.java自带了栈类,我在这里重新定义有些多余;
3.产生的练习题都是5个运算数。
本项目参考逆波兰式算法,并根据需求和自己的理解进行改进而成,如有好的建议,请多多指教!我将非常感谢!
PSP
PSP2.1
任务内容
计划完成需要的时间(min)
实际完成需要的时间(min)
Planning
计划
15
20
Estimate
估计这个任务需要多少时间,并规划大致工作步骤
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
测试(自我测试,修改代码,提交修改)
20
25
Reporting
报告
20
22
Test Report
测试报告
5
5
Size Measurement
计算工作量
5
10
Postmortem & Process Improvement Plan
事后总结 ,并提出过程改进计划
8
10