小学四则运算练习(JAVA编写)

源码在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<String> ss = new ArrayList<String>();
 2 
 3     public static void main(String[] args) throws Exception {
 4 
 5             System.out.println("Input a number:");
 6             int count = new Scanner(System.in).nextInt();
 7             File file =new File("./result.txt");
 8             FileOutputStream fops=null ;
 9 
10             try {
11                 fops = new FileOutputStream(file);
12 
13             } catch (FileNotFoundException e) {
14                 e.printStackTrace();
15             }
16             PrintStream ps= new PrintStream(fops);
17             ps.println("201571030125");
18             boolean f = true;
19             for (int i=0;i<count;i++) {
20                 String data = Data();
21                 String input = data;
22                 ss.add(input);
23                 if (input.equals("q"))
24                     break;
25                 else {
26                     Expression express = new Expression(input);
27                     f = express.getResult();
28                     if(!f) i--;
29                     else ps.println(data + "=" + express.getExpresult());
30                 }
31             }
32     }
33 
34 
35     //随机产生算式
36     public static String Data()
37     {
38         Random rand =new Random();
39         ArrayList<Integer> numlist = new ArrayList<Integer>();
40         ArrayList<String> express = new ArrayList<String>();
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=new String[size];
50         for(int i=0;i<numlist.size();i++){
51             num[i]=String.valueOf(numlist.get(i));
52         }
53         String exp="";
54         for(int j=0;j<num.length;j++)
55         {
56             express.add(num[j]);
57             express.add(operator[rand.nextInt(4)]);
58         }
59         //System.out.print(express);
60 
61         for(int i=0;i<express.size()-1;i++)
62             exp+=express.get(i);
63         return exp;
64     }

  Calulate类

 1 // 判断是否为操作符号
 2     public static boolean isOperator(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 int priority(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 static String twoResult(String operator, String a, String b) {
21         try {
22             String op = operator;
23             String rs = new String();
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             return String.valueOf(z);
49         } catch (NumberFormatException e) {
50             System.out.println("input has something wrong!");
51             return "Error";
52         }
53     }

  逆波兰式转换方法

 1  private void toRight() {
 2         Stack aStack = new Stack();
 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) expression
25                                     .get(position)) <= Calculate
26                                     .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 boolean getResult() {
 2 
 3 
 4         this.toRight();
 5 
 6         Stack aStack = new Stack();
 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个运算数。

  本项目参考逆波兰式算法http://blog.csdn.net/yunxiang/article/details/1918717,并根据需求和自己的理解进行改进而成,如有好的建议,请多多指教!我将非常感谢!

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

      

 

posted @ 2018-03-21 11:06  Rucr  Views(1432)  Comments(2Edit  收藏  举报