小学四则运算练习软件项目报告

github项目地址 : FourFundamentalOperations

实验要求

软件基本功能要求如下:
  • 程序可接收一个输入参数n,然后随机产生n道加减乘除练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间。
  • 为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符。同时,由于小学生没有分数与负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3/5+2=2.6,2-5+10=7等算式。
  • 练习题生成好后,将你的学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt中,不要输出额外信息,文件目录与程序目录一致。
  • 当程序接收的参数为4时,以下为输出文件示例。

软件附加功能要求如下:(请有余力的同学完成)
  • 支持有括号的运算式,包括出题与求解正确答案。注意,算式中存在的括号必须大于2个,且不得超过运算符的个数。(5分)
  • 扩展程序功能支持真分数的出题与运算,例如:1/6 + 1/8 + 2/323/24。注意在实现本功能时,需支持运算时分数的自动化简,比如 1/2+1/6=2/3,而非4/6。(5分)

1、需求分析

  该软件要求为随机生成四则运算,并给出答案。为了简化程序的复杂性,直接从逆波兰式入手。即随机生成逆波兰式,通过逆波兰式推导出计算表达式并计算出表达式的结果。这样方便处理附加问题中括号的情况。

2、功能分析

  • 可实现基本要求,即可生成数字在 0 和 100 之间,运算符在3个到5个之间的计算表达式,并计算出表达式的结果。
  • 随机可生成带括号的运算式,并不会超过云算符的个数

3、设计实现

  • 设计思路

 

  • 代码结构

 

4、运行测试

  • 测试输入错误字符:

 

 

 

 

 

 

  • 测试不输入生成算式的数量,默认为5,可正常运行

 

 

 

  • 测试生成算式

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5、核心代码

  • 随机生成逆波兰式
 1         ArrayList<String> strArr=new ArrayList<String>();
 2         List list = Collections.synchronizedList(strArr);
 3         N = new Random().nextInt(4)+2;
 4         synchronized(list) {
 5             strArr.clear();
 6             for (int i = 0; i < N; i++) {
 7                 strArr.add(ele.random_N());
 8             }
 9             for (int i = 0; i < N - 2; i++) {
10                 strArr.add(new Random().nextInt(strArr.size() - N + 1) + N - 1, ele.random_E());
11             }
12             strArr.add(strArr.size(), ele.random_E());
13         }
14         ele.setStrArr(strArr);
  • 通过逆波兰式生成运算式
 1  private static void pro_exp(ArrayList<String> strArr){
 2         String str = ele.getOperations();
 3         String ea,eb;
 4         Stack<String> expstack = new Stack<String>();
 5         for(String s : strArr){
 6             if(!str.contains(s)){//如果是数字,放入栈中
 7                 expstack.push(s);
 8             }else{
 9                 ea = expstack.pop();
10                 eb = expstack.pop();
11                 switch(s){
12                     case "+" :
13                         expstack.push( "("+eb+"+"+ea+")");
14                         break;
15                     case "-" :
16                         expstack.push("("+eb+"-"+ea+")");
17                         break ;
18                     case "*" :
19                         expstack.push( eb+"*"+ea);
20                         break;
21                     case "/" :
22                         expstack.push( eb+"/"+ea);
23                         break ;
24                 }
25             }
26         }
27         ele.setExp(expstack.pop());
28     }

 

  • 通过逆波兰式计算结果
 1  private static boolean evoe(ArrayList<String> strArr){
 2         String str = ele.getOperations();
 3         boolean flag = true;//判断过程中是否有负数或小数点
 4         int temp=0;//存放临时计算结果
 5         Stack<String> stack = new Stack<String>();
 6         for(String s : strArr){
 7             if(!str.contains(s)){//如果是数字,放入栈中
 8                 stack.push(s);
 9             }else{
10                 int a = Integer.valueOf(stack.pop());
11                 int b = Integer.valueOf(stack.pop());
12                 try {
13                     switch(s){
14                         case "+" :
15                             stack.push(String.valueOf(a+b));
16                             break;
17                         case "-" :
18                             temp = b-a;
19                             if(temp<0) flag=false;
20                             stack.push(String.valueOf(temp));
21                             break ;
22                         case "*" :
23                             stack.push(String.valueOf(a*b));
24                             break;
25                         case "/" :
26                             if(a==0) {a=1;flag=false;}
27                             temp = b/a;
28                             if(a*temp != b) flag=false;
29                             stack.push(String.valueOf(temp));
30                             break ;
31                     }
32                 } catch (Exception e) { }
33             }
34         }
35         ele.setResult(Integer.parseInt(stack.pop()));
36         return flag;
37     }

6、总结

  使程序模块化,即主要以面向对象的方法,我主要分为元素层和操作层,元素层为所有的操作符及数字,操作层为生成运算式和计算结果的这些方法。

7、展示PSP

PSP2.1

任务内容

计划完成需要的时间(min)

实际完成需要的时间(min)

Planning

计划

30

30

 Estimate

估计这个任务需要多少时间,并规划大致工作步骤

30

30

Development

开发

230

255

Analysis

需求分析 (包括学习新技术)

30

30

 Design Spec

生成设计文档

10

10

Design Review

设计复审 (和同事审核设计文档)

10

10

Coding Standard

代码规范 (为目前的开发制定合适的规范)

5

5

Design

具体设计

30

30

Coding

具体编码

120

130

Code Review

代码复审

10

10

est

测试(自我测试,修改代码,提交修改)

15

30

Reporting

报告

30

43

Test Report

测试报告

25

30

Size Measurement

计算工作量

2

3

Postmortem & Process

Improvement Plan

事后总结 ,并提出过程改进计划

3

10

项目总结

  此次项目看似难度不大,但要追求完美,需要多很多工作。最开始为了简化代码,并没有选择一般性的方法,即先生成运算式,再计算结果,而是选择直接随机生成逆波兰式,再将其转化为运算式并计算结果,本是为了简化和节约时间,但实际却花费了更多的时间,就从逆波兰式转化为带有括号的运算式,使我困惑了好久,但最终的收获也不少,让我对逆波兰式以及栈的操作有了很深的认识。就这样看似不大的项目,却有不少的干货,希望以后的实践中可以有更多的收获以及更大的进步。

posted @ 2018-03-19 21:59  城尘  阅读(445)  评论(3编辑  收藏  举报