【软件工程】小学四则运算 “软件”之初版

作业要求来源于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2186

我的github远程仓库的地址: https://github.com/RichardSkr/Simple-arithmetic-device

 


一、实验要求

像《构建之法》的人物阿超那样,写一个能自动生成小学四则运算题目的命令行 “软件”。

具体要求:任何编程语言都可以,命令行程序接受一个数字输入,然后输出相应数目的四则运算题目和答案。例如输入数字是 30, 那就输出 30 道题目和答案。 运算式子必须至少有两个运算符,运算数字是在 100 之内的正整数,答案不能是负数。 如:

 23 - 3 * 4 = 11

 扩展要求:

   1) 要求能出和真分数 (二分之一, 十二分之五,等)相关的练习题。

   2) 并且要求能处理用户的输入,并判断对错,打分统计。 要求能处理用户输入的真分数, 如 1/2, 5/12 等。

 初步拟定要实现的功能后,估计一下自己需要花多长时间。编程过程中记录自己实际用了多长时间。

 然后和同学们比较一下各自程序的功能、实现方法的异同等等。

 写博客纪录自己实现的过程和思路。


 二、功能模块

1、模块设计:

  (1)MainWork:主类,用于获取用户输入数据、输出获取的题目列表和答题情况

  (2)ExerciseUtils:练习题工具类,用于生成题目列表

  (3)ExerciseBean:练习题对象类,用于存储该题目的运算数、运算符和答案

2、数据结构:

  (1)ExerciseBean对象类中,用整型数组存储自动生成的运算数,用字符串数组存储自动生成的运算符;

    public int[] num;          //运算数
    public String[] operator;  //运算符
    public int degree = 3;     //难度
    public int answer = 0;         //答案

  (2)主类中采用了List对象集合将储存练习题列表;

List<ExerciseBean> exerciseList = ExerciseUtils.getExerciseList(exerciseCount);

3、算法:

  (1)随机生成运算数和运算符

for (int i = 0; i < degree; i++) {
    this.num[i] = rand.nextInt(100);
    int oper = rand.nextInt(4);
    if (i == degree - 1) {
        this.operator[degree - 1] = "=";
    } else {
        switch (oper) {
            case 0:
                this.operator[i] = "+";
                break;
            case 1:
                this.operator[i] = "-";
                break;
            case 2:
                this.operator[i] = "*";
                break;
            case 3:
                this.operator[i] = "/";
                break;
        }
    }
}

  (2)生成题目列表集合

for (int i = 0; i < exerciseCount; i++) {
    exerciseList.add(new ExerciseBean());
}

  (3)输出题目

for (int j = 0;j < 3;j++){
    exercise += exerciseList.get(i).num[j] + exerciseList.get(i).operator[j];
}
System.out.print(exercise);

   (4)判断运算顺序,先进行乘除运算,再进行加减运算,遍历运算符集合,通过用answer变量计算某运算符前后的数据,运算完后使当前运算符出栈,并把运算符前的数据替换成运算结果,运算符后的数据出栈;除法运算用变量numerator和denominator记录分子和分母,使分子参与运算,分母在运算符优先级的运算完后再参与运算这里只列出部分代码,完整代码请参考ExerciseBean对象类中的getAnswer()方法。

for (int i = 0; i < answer_operator.size(); ){  //先乘除
            if (answer_operator.get(i).equals("*")){
                answer = answer_num.get(i) * answer_num.get(i+1);
                answer_num.set(i,answer);
                answer_num.remove(i+1);
                answer_operator.remove(i);
            }else if (answer_operator.get(i).equals("/")){
                numerator = answer_num.get(i);
                answer = numerator;
                denominator = answer_num.get(i+1) * denominator;
                answer_num.set(i,numerator);
                numerator_index = i;
                answer_num.remove(i+1);
                answer_operator.remove(i);
            }else
                i++;
}

 


 

三:主要代码

  (1)MainWork

 1 import java.util.List;
 2 import java.util.Scanner;
 3 
 4 public class MainWork {
 5     public static void main(String arg[]){
 6         Scanner in =new Scanner(System.in);
 7         System.out.print("请输入出题数:");
 8         int exerciseCount=in.nextInt();
 9         String answer;//用户输入的答案
10         System.out.println("共有"+ exerciseCount + "题");
11         List<ExerciseBean> exerciseList = ExerciseUtils.getExerciseList(exerciseCount);
12         int score = 0;      //用户答题得分
13         for (int i = 0;i<exerciseList.size();i++){
14             String exercise = i+1 + "、";
15             for (int j = 0;j < 3;j++){
16                 exercise += exerciseList.get(i).num[j] + exerciseList.get(i).operator[j];
17             }
18             System.out.print(exercise);
19             answer = in.next();
20             if (answer.equals(exerciseList.get(i).getAnswer())){
21                 //System.out.println("答案"+exerciseList.get(i).getAnswer());
22                 score++;
23                 System.out.println("答对了,很优秀!");
24             }else {
25                 System.out.println("答错了,真遗憾!");
26                 System.out.println("正确答案是"+exerciseList.get(i).getAnswer());
27             }
28         }
29         System.out.println("答题结束!总成绩为"+score*100/exerciseCount+"分");
30     }
31 }

  (2)ExerciseBean对象类

  1 import java.util.*;
  2 
  3 public class ExerciseBean {
  4     public int[] num;          //运算数
  5     public String[] operator;  //运算符
  6     public int degree = 3;     //难度
  7     public int answer = 0;         //答案
  8     public ExerciseBean(){
  9         do {
 10             createExercise();
 11         }while (answer < 0);
 12     }
 13 
 14     /**
 15      * 习题初始化
 16      */
 17     private void createExercise(){
 18         Random rand =new Random();
 19         this.num = new int[degree];
 20         this.operator = new String[degree];
 21             for (int i = 0; i < degree; i++) {
 22                 this.num[i] = rand.nextInt(100);
 23                 int oper = rand.nextInt(4);
 24                 if (i == degree - 1) {
 25                     this.operator[degree - 1] = "=";
 26                 } else {
 27                     switch (oper) {
 28                         case 0:
 29                             this.operator[i] = "+";
 30                             break;
 31                         case 1:
 32                             this.operator[i] = "-";
 33                             break;
 34                         case 2:
 35                             this.operator[i] = "*";
 36                             break;
 37                         case 3:
 38                             this.operator[i] = "/";
 39                             break;
 40                     }
 41                 }
 42             }
 43     }
 44 
 45     /**
 46      * 计算算式答案
 47      * 返回答案字符串
 48      */
 49     public String getAnswer(){
 50         int answer = 0;
 51         int denominator = 1;//分母
 52         int numerator = 1;  //分子
 53         int numerator_index = -1;  //分子坐标
 54         List<Integer> answer_num = new ArrayList<Integer>();
 55         List<String> answer_operator = new ArrayList<String>();
 56         for (int i = 0;i < num.length;i++){
 57             answer_num.add(num[i]);
 58             answer_operator.add(operator[i]);
 59         }
 60         for (int i = 0; i < answer_operator.size(); ){  //先乘除
 61             if (answer_operator.get(i).equals("*")){
 62                 answer = answer_num.get(i) * answer_num.get(i+1);
 63                 answer_num.set(i,answer);
 64                 answer_num.remove(i+1);
 65                 answer_operator.remove(i);
 66             }else if (answer_operator.get(i).equals("/")){
 67                 numerator = answer_num.get(i);
 68                 answer = numerator;
 69                 denominator = answer_num.get(i+1) * denominator;
 70                 answer_num.set(i,numerator);
 71                 numerator_index = i;
 72                 answer_num.remove(i+1);
 73                 answer_operator.remove(i);
 74             }else
 75                 i++;
 76         }
 77         for (int i = 0; i < answer_operator.size(); ){  //后加减
 78             if (answer_operator.get(i).equals("+")){
 79                 if (i == numerator_index){
 80                     answer_num.set(i+1,answer_num.get(i+1) * denominator);
 81                 }else if ((i+1) == numerator_index){
 82                     answer_num.set(i,answer_num.get(i) * denominator);
 83                 }
 84                 answer = answer_num.get(i) + answer_num.get(i+1);
 85                 answer_num.set(i,answer);
 86                 answer_num.remove(i+1);
 87                 answer_operator.remove(i);
 88             }else if (answer_operator.get(i).equals("-")){
 89                 if (i == numerator_index){
 90                     answer_num.set(i+1,answer_num.get(i+1) * denominator);
 91                 }else if ((i+1) == numerator_index){
 92                     answer_num.set(i,answer_num.get(i) * denominator);
 93                 }
 94                 answer = answer_num.get(i) - answer_num.get(i+1);
 95                 answer_num.set(i,answer);
 96                 answer_num.remove(i+1);
 97                 answer_operator.remove(i);
 98             }else
 99                 i++;
100         }
101         this.answer = answer/denominator;
102         if (denominator != 1){
103             int gongyinshu = 1;
104             int smaller = answer > denominator ? denominator : answer;
105             for (int i = 1; i <= smaller; i++) {
106                 if (answer % i == 0 && denominator % i == 0) {
107                     gongyinshu = i;
108                 }
109             }
110             answer = answer / gongyinshu;
111             denominator = denominator / gongyinshu;
112             return answer + "/" + denominator;
113         }else
114             return answer+"";
115     }
116 
117     //设置题目难度
118     private void setDegree(int degree){
119         this.degree = degree;
120     }
121 
122 }

  (3)ExerciseUtils工具类

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 public class ExerciseUtils {
 5     public static List<ExerciseBean> getExerciseList(int exerciseCount) {
 6         List<ExerciseBean> exerciseList = new ArrayList<ExerciseBean>();
 7         for (int i = 0; i < exerciseCount; i++) {
 8             exerciseList.add(new ExerciseBean());
 9         }
10         return exerciseList;
11     }
12 }

 


 

四、运行结果


 

五:时间表

PSP2.1 Personal Software Process Stages Time Senior Student Time
Planning 计划 20 15
.Estimate 估计这个任务需要多少时间 20 15
Development 开发 120 150
.Analysis 需求分析 (包括学习新技术) 20 15
.Design Spec 生成设计文档 0 0
.Design Review 设计复审 5 10
.Coding Standard 代码规范 10 10
.Design 具体设计 20 15
.Coding 具体编码 35 70
.Code Review 代码复审 10 5
.Test 测试(自我测试,修改代码,提交修改) 20 25
Reporting 报告 9 6
· 测试报告 4 4
· 计算工作量 5 2
· 并提出过程改进计划 0 0

 


 

六、遇到的问题及如何解决

  (1)问题:在设计运算符优先级时,优先级相同的运算符只有出现一次时只运算一次,比如a*b+c可以运算正确因为“*”和“+”优先级不一样,而a*b/c就只能进行一次运算符的运算。

  解决方法:经过测试之后发现是由于在for循环里面,运算完的运算符出栈了,但是下标i进行了++操作,导致不能获取到运算符集合里的下一个运算符,所以在改为在没有这一优先级的运算符时才进行下标++操作。

  (2)问题:进行除法运算时,使用"/"运算符只能得到整型数据而不能得到真分数。

  解决方法:定义两个变量分别存储分子和分母的值,分母初始化为1,在进行除法运算时,记录分子下标,并为分子和分母赋值,进行加减法运算时判断运算符前后是否有存储分子的数据,有的话则使另一个运算数与分母相乘,在进行优先级运算后,当分母不为1是,把结果和分母进行约分并用字符串组合起来,得到最终结果。

posted @ 2018-10-15 12:34  海芋  阅读(303)  评论(3编辑  收藏  举报