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

【coding.net地址】:https://git.coding.net/aspirinone/work2-2016011995.git

 

【测试】在git上clone项目以后,在命令行编译为class文件,再运行java Main 10

 

【计划】项目完成步骤

 

【开发过程】

一、需求分析

(1) 程序可接收一个输入参数n,然后随机产生n道加减乘除练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间。

(2) 每个练习题至少要包含2种运算符,而且练习题在运算过程中不得出现负数与非整数,比如不能出 3÷5+2=2.6,2-5+10=7等算式。

二、功能设计

  基本要求:根据需求随机出题并得出答案。

三、设计实现

(1)Main.java类启动程序,接收参数n,引用ChuangJian.java

(2) ChuangJian.java类创建一个result.txt文件(如果已有一个txt文件,要事先删除),输出学号和题目,引用ChuTi.java类

 

 1 public class Main {
 2     public static void main(String[] args) {
 3     Scanner input = new Scanner(System.in);
 4     System.out.print("请输入题目数量:");
 5     int n = 0;
 6     try{
 7         n = input.nextInt();
 8     }catch (Exception e){
 9         Scanner in = new Scanner(System.in);
10         System.out.print("输入有误,请输入数字:");
11         n = in.nextInt();
12     }
13         ChuangJian.File(n);
14     }
15 }

 

 1 public class ChuangJian {
 2     public static void File(int n){
 3         try{
 4             File file = new File("result.txt");
 5             if (file.exists()) {
 6                 file.delete();
 7             }
 8             if(file.createNewFile()){
 9                 FileOutputStream txtfile = new FileOutputStream(file);
10                 PrintStream p = new PrintStream(txtfile);
11                 p.println("2016011995");
12                 for(int i=0;i<n;i++){
13                     p.println(ChuTi.crePro());
14                 }
15                 txtfile.close();
16                 p.close();
17                 System.out.println("文件创建成功!");
18             }
19         }
20         catch(IOException ioe) {
21             ioe.printStackTrace();
22         }
23     }
24 }

 

(3)ChuTi.java类中随机产生3-5个操作符,并随机产生相应的数字,随机产生的操作符是通过下标数组确定的:(部分代码)

   

1  public static String crePro(){
2         Random random = new Random();
3         String[] operator = {"+","-","×","÷"};
4 
5         int operatorCount = 3+random.nextInt(3); //操作符的个数3-5
6         int[] num = new int[operatorCount+1]; 
7         int[] index = index(operatorCount); //操作符的下标
8         String s = new String();
9 }

 

 1 private static int[] index(int n){ //产生操作符的下标数组
 2         Random random = new Random();
 3         int similar=0;
 4         int[] a = new int[n];
 5         for(int j=0;j<n;j++){
 6             a[j] = random.nextInt(4);
 7         }
 8         for(int j=1;j<n;j++){
 9             if(a[0]==a[j]) similar++;
10         }
11         if(similar==n-1) return index(n); 
12         else {
13             return a;
14         }
15     }

 

(4)Jisuan.java类用于判断运算过程中是否出现负数和小数,使用了调度场算法和逆波兰表达式,详见算法详解部分。

 

四、算法详解

在Jisuan.java类中运用了以下思想:

参考了博客《调度场算法与逆波兰表达式》:https://blog.csdn.net/acdreamers/article/details/46431285

调度场算法规则如下:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,若是右括号或优先级低于栈顶符号,则弹出栈 顶元素并输出,将当前元素压入栈,一直到输出后缀表达式为止。

逆波兰表达式求值步骤:

 *初始化一个空堆栈

 *如果字符是一个操作数,把他压入堆栈

 *如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈,如果不能够弹出两个操作数,那么后缀表达式的语法错误

 *到后缀表达式末尾,从堆栈中弹出结果,若后缀表达式格式正确,那么堆栈应该为空

    

(1)使用HashMap键值对规定字符优先级:

1 public static int calculate(String s) {
2         Stack<Integer> stack1 = new Stack<>(); //放数字
3         Stack<String> stack2 = new Stack<>(); //放操作符
4         HashMap<String, Integer> hashmap = new HashMap<>(); //存放运算符优先级
5         hashmap.put("(", 0);
6         hashmap.put("+", 1);
7         hashmap.put("-", 1);
8         hashmap.put("×", 2);
9         hashmap.put("÷", 2);

 

(2)对字符串中的操作符一个个处理,遇到数字则压入栈,calculate()函数用于将运算过程中出现负数和小数的情况都返回为负数,后续排除。

 1 switch (c) {
 2                     case '=': { //遇到等号
 3                         String stmp;
 4                         while (!stack2.isEmpty()) { //当前符号栈里面还有+ - * /,即还没有算完
 5                             stmp = stack2.pop();
 6                             int a = stack1.pop();
 7                             int b = stack1.pop();
 8                             int sresulat = calculate(b, a, stmp);
 9                             if(sresulat<0)
10                                 return  -1;
11                             stack1.push(sresulat);
12                         }
13                         break;
14                     }
15 
16                     default: {  //遇到加减乘除等操作符
17                         String stmp;
18                         while (!stack2.isEmpty()) { //如果符号栈有符号
19                             stmp = stack2.pop(); //当前符号栈,栈顶元素
20                             if (hashmap.get(stmp) >= hashmap.get(String.valueOf(c))) { //比较优先级
21                                 int a = stack1.pop();
22                                 int b = stack1.pop();
23                                 int sresulat =calculate (b, a, stmp);
24                                 if(sresulat<0)
25                                     return  -1;
26                                 stack1.push(sresulat);
27                             }
28                             else {
29                                 stack2.push(stmp);
30                                 break;
31                             }
33                         }
34                         stack2.push(String.valueOf(c));  //将符号压入符号栈
35                         break;
36                     }
37                 }

 

【测试】

 

【时间分配】

【PSP】

PSP

任务内容

计划时间(min)

完成时间(min)

Planning

计划

20

20

 Estimate

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

30

20

Development

开发

600

2000

Analysis

需求分析

20

25

Design Spec

生成文档


5


10

 Design Review

设计复审


20


20

Coding Standard

代码规范


20


20

Design

具体设计

60

180

Coding

具体编码

300

900

Code Review

代码复审

30

600

Test

测试

5

80

Reporting

报告

160

400

Test Report

测试报告

120

360

Size Measurement

计算工作量

10

10

Postmortem & Process Improvement Plan

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

30

30

 

  

 

posted @ 2018-03-24 10:40  向海之鲸  阅读(293)  评论(4编辑  收藏  举报