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

代码仓库地址:https://coding.net/u/Siamese_miao/p/fourArithmetic/git?public=true

测试效果见src下生成的result.txt文件


一、 需求分析

1.  使用JAVA编程语言。

2.  接收一个输入参数n,随机产生n道四则运算练习题,符号用+-*÷来表示。

3.  每个数字在 0 和 100 之间。

4.  运算符在3个到5个之间并且每道练习题至少要包含2种运算符。

5.  运算过程中不得出现负数与非整数。

6.  将学号和生成的练习题及对应答案输出到文件“result.txt”中,不输出额外信息。

附加需求

1.  产生带括号的四则运算并求解,算式中存在的括号必须大于2个,且不得超过运算符的个数。

2.  产生真分数的加减法运算,运算过程中都为最简真分数。


二、 功能设计

基本功能

能够根据用户输入的参数n随机产生n道符合要求的四则混合运算练习题,自动算出答案,并将式子与答案以文档的形式呈现。

扩展功能

支持有括号的运算、支持最简真分数的加减运算


三、 设计实现

首先,我从简单四则混合运算开始,接着在这的基础上完成了分数运算,最后再思考带括号的运算。我先按这个顺序分别创建了项目,单独编写,最后才分类规整到一个项目中,如图我分为5个类。

  • Main类:主类,负责接收命令行的参数并启动程序。
  • fileCreate类:创建文件类,负责每次出题类型并产生result.text文件,将学号与练习题写入文件。
  • formula类:式子类,负责根据调用产生同种类型的式子,含有arithmetic(简单四则运算)、bracket(带括号的四则运算)、score(真分数加减运算)三种函数。
  • calculate类:计算类,负责各种计算,含有结果运算、有条件产生减数、有条件产生除数、有条件产生分子、有条件产生分母、判断数的大小、求取最大公因数、求取最小公倍数、分数相加、分数相减等10个方法。

各类与各函数之间的关系如下图。


四、 算法详解

我的算法大多数比较简单,多采用递归的方式。

  • 简单四则运算

由于符号由+-*÷表示,而计算机计算使用+-*/,所以我先定义了两个符号数组与定义两个字符串,一个作为显示式子用,一个用于计算,数组下标一一对应。再由范围为3~5的随机数确定式子的符号数,再由两个整型数组存储算数与符号对应的下标值,值皆由随机数产生,算数范围为0~100,下标值范围为0~3。式子使用for循环,每次将一个算数与一个符号加入字符串中,执行完循环后,最后再加上最后一个算数。计算后,连同式子一并输出。在计算时,我使用java调用js中的eval(String)函数求解。因为式子必须包含两种运算符以上,在输出前需要判断是否所有符号相同,不相同则不输出并重新运行程序。

 1 // 计算结果
 2     public static Object result(String temp) {
 3         ScriptEngineManager sem = new ScriptEngineManager();
 4         ScriptEngine se = sem.getEngineByName("js");
 5         Object last = 0;
 6         try {
 7             last = se.eval(temp);
 8         } catch (ScriptException e) {
 9             e.printStackTrace();
10         }
11         return last;
12     }

计算结果

考虑到运算过程中不能出现小数与负数,所以在除号与减号部分需要做处理,当减数大于被减数时,重新生成减数直至不大于被减数,当除数无法整除被除数或为0时,重新生成除数。后来在测试时发现两两数字符合规则,然而整条式子却仍会出现负数与小数。经过思考,一般出现于连减、连除、减号后乘除因优先级不同的式子中,所以我设了个判断,减号后一位只能为加号,除号后一位只能为加减号,由此解决了运算过程中出现负数或小数的问题。

 1 public static String arithmetic() {
 2         int m, j;
 3         char[] p = new char[] { ‘*‘, ‘+‘, ‘÷‘, ‘-‘ };
 4         char[] q = new char[] { ‘*‘, ‘+‘, ‘/‘, ‘-‘ };
 5         String temp1 = "";
 6         String temp2 = "";
 7         m = (int) (Math.random() * 3 + 3); // 符号数
 8         int[] num = new int[m + 1]; // 数字
 9         int[] key = new int[m]; // 符号所在的下标
10         for (j = 0; j <= m; j++) {
11             num[j] = (int) (Math.random() * 101);
12         }
13         for (j = 0; j < m; j++) {
14             if (j > 0 && key[j - 1] == 3) { // 减号后仅允许加号,防止负数出现
15                 key[j] = 1;
16             } else if (j > 0 && key[j - 1] == 2) {
17                 key[j] = (int) (Math.random() * 2); // 除号后仅允许乘号与加号,防止负数
18             } else {
19                 key[j] = (int) (Math.random() * 4); // 随机符号
20             }
21             temp1 += String.valueOf(num[j]) + String.valueOf(p[key[j]]);
22             temp2 += String.valueOf(num[j]) + String.valueOf(q[key[j]]);
23             if (key[j] == 3) {
24                 num[j + 1] = calculate.decide1(num[j], num[j + 1]); // 选定小于被减数的减数
25             } else if (key[j] == 2) {
26                 num[j + 1] = calculate.decide2(num[j], num[j + 1]); // 确保能够整除
27             }
28         }
29         j = 0;
30         while (j < (m - 1) && key[j] == key[j + 1])
31             j++; // 与第一个符号相同数
32         if (j == (m - 1))
33             return arithmetic(); // 若所有符号相同,该式子不算,保证有两种运算符
34         else {
35             temp1 += String.valueOf(num[m]);
36             temp2 += String.valueOf(num[m]);
37             return temp1 + "=" + calculate.result(temp2);
38         }
39     }

简单四则运算

  • 分数的加减

在基本混合运算的基础上修改出分数加减就显得简单许多。最主要的就是分数的通分约分,解决了这个问题,程序就基本完成了。因为没有优先级的关系,可以一边补充式子一边计算从而修改算数,无需限定符号。这也是我最满意的代码。

 1 // 真分数分式
 2     public static String score() {
 3         char[] p = new char[] { ‘+‘, ‘-‘ };
 4         int j;
 5         String temp1 = "";
 6         int m = (int) (Math.random() * 3 + 3);
 7         int[] key = new int[m]; // 运算符
 8         int[] x = new int[m + 1]; // 分子
 9         int[] y = new int[m + 1]; // 分母
10         int[] sum = new int[2];// 中途运算结果
11         for (j = 0; j <= m; j++) {
12             x[j] = (int) (Math.random() * 20 + 1);
13             y[j] = calculate.decide3(x[j]);
14         }
15         sum[0] = x[0];
16         sum[1] = y[0];
17         for (j = 0; j < m; j++) {
18             key[j] = (int) (Math.random() * 2);
19             if (key[j] == 0) { // 结果小于1
20                 int[] num = new int[2];
21                 num = calculate.fracAdd(sum[0], sum[1], x[j + 1], y[j + 1]);
22                 if (num[0] >= num[1]) {
23                     key[j] = 1;
24                 } else {
25                     sum = num;
26                 }
27             }
28             if (key[j] == 1) { // 结果不为负数
29                 int[] num = new int[2];
30                 num = calculate.fracSub(sum[0], sum[1], x[j + 1], y[j + 1]);
31                 if (num[0] < 0) {
32                     x[j + 1] = calculate.decide4(sum[0], sum[1]);
33                     y[j + 1] = sum[1];
34                     num = calculate.fracSub(sum[0], sum[1], x[j + 1], y[j + 1]);
35                 }
36                 sum = num;
37             }
38             temp1 += String.valueOf(x[j]) + "/" + String.valueOf(y[j]) + String.valueOf(p[key[j]]);
39         }
40         j = 0;
41         while (j < (m - 1) && key[j] == key[j + 1])
42             j++; // 与第一个符号相同数
43         if (j == (m - 1))
44             return score(); // 若所有符号相同,该式子不算,保证有两种运算符
45         else {
46             temp1 += String.valueOf(x[m]) + "/" + String.valueOf(y[m]);
47             return temp1 + "=" + sum[0] + "/" + sum[1];
48         }
49     }

分数运算

  • 含括号的运算

这部分由于优先级的改变以及时间关系,还没有改善完成,目前仍无法确保运算结果不含小数与负数。

我思考了很久如何随机生成括号,最后受到一篇博客(当时忘记保存网址,现在已经找不到了,抱歉)使用概率的启发,我以一定概率的方式生成左括号,记录生成左括号的个数以及未匹配的左括号的个数,以一定概率生成右括号,最后补齐。

 1 if (((brack * 2) <= (n - 1)) && (((int) (Math.random() * 2)) == 0)) // 以一定概率生成左括号,概率为1/2
 2             {
 3                 temp1 += "(";
 4                 temp2 += "(";
 5                 brack++;
 6                 brack_left++;
 7                 temp1 += num[++i]; // 生成左括号后必须生成一个数字和运算符,不然可能出现(15)这样的错误
 8                 temp2 += num[i];
 9                 op = (int) (Math.random() * 4);
10                 temp1 += Op[op];
11                 temp2 += p[op];
12                 if (op == 3)
13                     div = 1;
14                 else if (op == 1)
15                     div = 2;
16             }

概率生成左括号


五、 测试运行

进入src文件下,输入javac -encoding utf-8 Main.java 编译出相应的class文件,再输入java Main 20进行测试,我们可以先测试java Main abc或java Main 1500或java Main 0,在这里我使用的jdk版本为jdk1.8.0_25。

测试结果如下图。

除此之外,我还学习了使用myeclipse做单元测试,测试结果如图所示,我从测试结果发现,当文件存在时,删除重建会耗时约2秒(以5道算式为例)。


六、 总结

一开始由于我不清楚我能否完成附加功能,所以我用一个Main类的主函数完整的写一个简单的四则运算。但是调试时花费了许多时间,并且十分不灵活,所以我把函数中重复的计算部分抽离出来,写成静态方法,再进行测试,调试起来方便许多,想要修改哪一个部分的代码只需要在相应的函数中修改即可。同理,分数运算与括号运算我也这么做,由此我创建了三个项目。当三个项目都差不多完成时,我意识到其中有许多重复之处,所以我将它们分类并合在一个项目中。

除了主类包含了一个主函数外,我把我的程序分成3个类,各自分工,每个类中我尽量把各个功能细分成各种小方法,尤其在calculate类中每个方法不超过10行。具体可看第三点的关系图。方法间的逐级调用给调试和测试都带来了很多便利,尤其在测试优化方面,同时也增加了代码的可移植性和可读性。


七、 PSP


PSP2.1


任务内容


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


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


Planning


计划


30


20


·        Estimate


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


30


20


Development


开发


1515


2470


·        Analysis


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


180


150


·        Design Spec


·         生成设计文档


50


30


·        Design Review


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


10


15


·        Coding Standard


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


5


5


·        Design


·         具体设计


10


15


·        Coding


·         具体编码


1200


1800


·        Code Review


·         代码复审


30


15


·        Test


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


30


440


Reporting


报告


75


170


·         Test Report


·         测试报告


10


15


·         Size Measurement


·         计算工作量


5


5


·         Postmortem & Process Improvement Plan


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


60


150

这次的代码我思考了很久,在敲代码与测试方面远远的超过了计划的时间,源于我低估了代码的复杂度。虽然有思路,但把思路实现却花费了特别多的时间,思虑的不充分总是让程序报错,再加上我对java掌握的不够,所以我在编程花费了许多许多时间,有很多时候就是不知如何实现需求。再者,打这篇博客报告也花费了很多时间,但也再次整体的梳理了我的思路。

在这次打代码的过程中,我学到了四个方法。

一个是使用java调用js的eval()函数,这个方法可以输入字符串型的算式然后直接算出答案。

另外一个是在用命令运行符使用Java Main 20作为命令时,应使用

1 n=Integer.parseInt(args[0]);

来获取输入的参数,而我在myeclipse使用的一直是

1 Scanner in = new Scanner(System.in);
2 n=in.nextInt();

语句执行。

还有一个是以概率的方式随机生成括号。

最后是使用Debug修改错误代码,使用单元测试优化程序提高性能。



这次的学习让我意识到自己的不足,我以后会继续努力。

原文地址:https://www.cnblogs.com/maomao-miao/p/8641912.html

时间: 2024-10-09 18:44:41

2016012034+小学四则运算练习软件项目报告的相关文章

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

 小学四则运算练习软件项目报告 项目克隆地址:https://git.coding.net/chenf640/workhome2_2.git 目录: 一.需求分析 二.功能设计 三.设计实现 四.算法详解 五.测试运行 六.代码展示 七.psp 八.总结 -------------------------------------------------- 一.需求分析 (一)功能需求  基本功能: 程序可接收一个输入参数n,然后随机产生n道加减乘除(分别使用符号+-*÷来表示)练习题. 每个数字

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

2016012075+小学四则运算练习软件项目报告 一.需求分析 二.功能设计 三.设计实现 四.算法详解 五.测试详解 六.代码展示 七.总结 八.PSP展示 coding.net地址:https://git.coding.net/sparkleStar/arithmetic.git,代码在Main.java中 一.需求分析 1.编写目标 使用Java编程语言,独立完成一个3到5个运算符的四则运算练习的命令行软件开发. 2.基本功能需求 (1)程序可接收一个输入参数n,然后随机产生加减乘除(分

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

项目报告目录: 一.感想 二.需求分析 三.功能设计 四.设计实现 五.算法详解 六.测试运行 七.总结反思 八.PSP展示 代码仓库地址:https://git.coding.net/Vsmile1997/symx.git测试效果见src下生成的result.txt文件 一.感想 我把感想写在第一部分,是想首先谈谈完成这个项目的体验和感悟.重新梳理程序的代码思路,满满的完成任务的成就感和如释重负的轻松感. 从拿到作业的起初,我把问题过度放大了.Java?我还要重新拿起那本大厚书学习Java?出

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

需求分析 首先明确项目需要,一个可以定做小学四则运算的程序.所以需要我们能够随机生成不同的四则运算,范围应在100以内,包含"+,-,*,÷"四种操作.要求:不存在小数,题目尽量不重复. 功能设计 基本功能应当包括,读入用户想要定制的算式数,以及对应的运算符数量,然后生成对应数目和难度的四则运算式子.并由程序自己计算,给出相应的答案. 扩展功能可以用:在算式中包含括号,计算存在真分数的式子. 设计实现 由计算机生成随机的第一个数字.运算符.后续数字.完成计算.显示结果等等. 在生成后续

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

项目地址:https://git.coding.net/meiyoupiqidefan/Four-Operations.git 目录: 一.需求分析 二.功能设计 三.设计实现 四.算法详解 五.测试运行 六.粘贴代码 七.总结 八.展示PSP ---------------------------- 一.需求分析 由于每次出题的数目不定,所以要求题数参数n由控制台输入 小学生水平有限,故每个数字在 0 和 100 之间,运算符在3个到5个之间. 为了让小学生得到充分锻炼,每个练习题至少要包含2

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

我的项目源码地址:https://coding.net/u/Dearpangpang/SiZeYunSuan.git/git.html 项目需求: 软件基本功能要求如下: 程序可接收一个输入参数n,然后随机产生n道加减乘除(分别使用符号+-*÷来表示)练习题,每个数字在0和100之间,运算符在3个到5个之间. 为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符.同时,由于小徐生没有分数和负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出(3÷5+2=2.6,2-5+10

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

Github的仓库主页链接地址:https://github.com/cy0325/CulClation.git 一.实验要求 软件基本功能要求如下: 程序可接收一个输入参数n,然后随机产生n道加减乘除练习题,每个数字在 0 和 100 之间,运算符是3-4个. 为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符.同时,由于小学生没有分数与负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3/5+2=2.6,2-5+10=7等算式. 练习题生成好后,将你的学号与生成的

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

1.仓库地址:https://git.coding.net/FrrLolix/Calculate.git 2.需求分析: ①程序接受一个输入的参数n后,随机生成n道四则运算式,其中要保证生成的运算式的运算符在3-5个之间,同时程序对生成的运算式自动求解,结果和运算式一同输出到result.txt文件中. ②因为面向对象是小学生,所以要保证生成的运算式中不出现负数和小数,运算的结果也不能出现负数和小数. ③程序需要判断输入的参数n是否合法,在不合法时要进行一定的处理. ④在原有的基础上,生成的运算

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

作业源代码地址:https://git.coding.net/mal123/elementary_arithmetic.githttps://git.coding.net/mal123/elementary_arithmetic.githttps://git.coding.net/mal123/elementary_arithmetic.githttps://git.coding.net/mal123/elementary_arithmetic.githttps://git.coding.net