项目地址:https://gitee.com/wxrqforever/object_oriented_exp1.git

一、需求分析:
  一个基于控制台的四则运算系统,要能实现生成并计算含有真,假分数,整数的不超过三个运算符带有括号的四则运算表达式,并且要能根据用户所提交的答案生成答题报告,答题报告中主要包括,本次答题的正确,错误,和重复表达式出现的情况。生成的表达式和答案要存入文件中。对生成的表达式有如下要求,不能在过程中产生负数,因为小学生并不会计算负数,以及不能出现除0的情况,因为小学生不会计算除以0。
  从整个需求来看,大致可以分为三个模块,生成表达式,表达式计算(包括将表达式和答案写入文件),答题报告的生成(包括表达式的查重和根据输入完成的校验)。各个模块之间关系密切,故采用由下至上的不断迭代的开发模式,先开发最底层的各个桩模块,在开发每个桩模块时再采用测试驱动开发的方法,从编写小的测试用例开始开发桩模块,当对桩模块进行整合时,再编写测试模块,这样当开发完成后测试也就完成了。
  生成表达式模块:主要的关键点在于如何能够全覆盖所有不超过三个运算符含有真,假分数,整数的可以带有括号的四则运算表达式。在忽略优先级的条件下,我们观察表达式形如(1+2+3)*6,1+2+3, 1+2,的三个表达式,我们会发现任何一个复杂的表达式均可看作,其少一个运算符的表达式和一个运算符以及一个运算数构成,如上的例子中
(1+2+3)*6 可以看作是由(1+2+3)和*以及6构成,而1+2+3 则可以看做是由1+2 和+以及3构成。这就给了一个思路只要编写一个能随机生成所有情况下的带一个运算符的表达式,就可以通过不断添加运算符和运算操作数的方式而穷尽所有的可能。
  表达式计算:可采用将随机生成的表达式转换为后缀,在对后缀表达式进行计算完成。
  答题报告的生成:关键点在于如何实现查重,首先我们要明白何为重复的表达式?根据题目中的定义“程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左优先计算的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。" 仔细观察题目中所给的两个例子,你会发现这里所说的重复的意思就是你不能破坏原本计算时的优先级,在这个基础上你可以交换加法或者乘法的。解析一下题中的例子,比如3+(2+1)和1+2+3这两个题目,为什么是重复的呢?按照优先级,我们是如何计算左边题目的,是先计算2+1的这个加法再计算3加上2+1的结果的这个加法的对吧,而右边这个题目根据加法的左结合,先计算1+2 的这个加法 再计算3加上1+2 这个结果的加法,运算时的符号的优先级并没有被改变仅仅改变了加法的左右操作数,满足重复的定义,所以是重复的。
  再看一个不重复的例子,1+2+3和3+2+1,同样的左边的题目,先计算的是1+2的这个加法再计算3加上1+2的结果的这个加法,而右边的则是先计算3+2的这个加法再计算1加上3+2的结果的加法.可以理解为在进行运算时整个运算的流程是不同的,所以是不同的表达式.
通过上述的分析我们可以看到如何判定两个表达式是否重复关键在于如果在计算这两个表达式时的流程完全一致或者仅在加法或者乘法运算时交换了左右操作数则这样的两个运算表达式是重复的,这样的分析很容易让我们相到用后缀表达式解决查重,但仅仅依靠后缀表达式是不够的,后缀表达式是能够体现计算过程但却无法用于判断两个表达式之间计算过程是否相同的直接体现,这是·两个重复的表达式很可能会有不同后缀表达式。比如以(1+2)*3+5和3*(1+2) +5 为例,(1+2)*3+5的后缀表达式为1 2 + 3 * 5 + 而3*(1+2) +5的后缀表达式为3 1 2 + * 5+,虽然是相同运算过程的体现但表达式之间的差距却非常的大,那该如何解决?
  所谓相同的运算过程就是,你在做什么运算我也做什么运算,你的操作数是啥我的操作数也是啥,出于这个引入一个新的表达式,我将其命名为查重表达式,他的结构是运算在先后面跟着这个运算符的操作数,以上述为例(1+2)*3+5的查重表达式就为: +12 * 3 +5 这个表达式的含义就是第一个运算的是加法,加法的操作数是2 和3 第二个运算是乘法,乘法的操作数是前一步计算的结果和3以此类推,而3*(1+2) +5的查重表达式为:+12 * 3+5 与上述完全一致!这样在做查重是只需判断查重表达式是否一致或者在查重表达式中第一个字符为‘+’ 或者‘*’的情况下后续的两个操作数互换位置后是否一致即可。也就是说上述的查重表达式于+21 * 3+5 也是等价的。
那该如何生成查重表达式,所谓的查重表达式就是描述表达式正在运算的过程,那就在你使用后缀表达式计算时,去生成即可。算法之后给出
二、功能设计:
功能设计如图:

com.wx.appEntrance是作为项目的入口。
com.wx.test 是作为测试功能使用
com.wx.randomTool是作为生成随机的四则运算表达式的,共有四个类组成其中RandExpressionExport(可直接生成表达式)是顶层类,是对RandOperatorNumberExport(可随机生成各类操作数和操作符)进一步封装,而RandOperatorNumberExport是对RandomExportMachine(可生成数字和字符)的进一步封装,Ruler则是描述生成表达式的功能.
com.wx.expression是描述表达式的结构
com.wx.calculateTool是用于计算表达式,PostfixExpression用于生成后缀表达式,CalculateRuler描述计算规则,CalculateExpression顶层类对可直接计算表达式,对前面两个类的封装。
com.wx.fileIO用于实现文件操作
com.wx.expressionCnki 用于实现表达式的查重,工具类.
com.wx.report 用于生成答题报告.

三、代码实现

3.1表达式类主要用于存储表达式的代码,如下:

3.2.1 用于随机产生一个表达式的顶层类RandExpressionExport中的产生随机表达式getExpression方法代码如下:

3.2.2 用于随机产生一个表达式的顶层类RandExpressionExport中的随即产生一个操作符表达式的getOneOperatorExpression方法的代码如下:

(其余多操作符的情况均是对该方法的进一步封装)

3.2.3用于随机产生一个表达式的顶层类RandExpressionExport中的随即产生带有两个操作符的表达式的getTwoOperatorExpression方法的代码如下:

3.3.1用于将表达式转换成后缀表达式的PostfixExpression类中的getPostFixExpression代码如下:

3.3.2用于计算后缀表达式的CalculateExpression类中的calculatePostFixExpression方法代码如下:

3.3.3用于描述计算规则的CalculateRuler中的用于化简表达式的方法simplificationFracrion的代码如下:

4.1用于实现查重的Cnki类中的得到查重表达式的getCnkiExpressionArray方法的代码如下:

4.2用于实现查重的Cnki类中的判断两个表达式是否重复的代码如下:

4.3用于生成报告的AnswerResport中生成答题报告getAnswerResport方法的代码:
4.4用于生成报告的AnswerResport中生成查重报告cnkiExpressionAnswerReport方法的代码:

四、测试运行:

测试截图如下:

输入题目数为10 生成的数字范围为10

文件中的截图如下:

对于查重进行单独测试:
当输入的表达式为1+2+3 与3+(2+1)时,截图如下:其中第一,二行为1+2+3的后缀表达式和查重表达式,第三,四行为3+(2+1)的后缀表达式和查重表达式。

第五行为查重结果,余下的为查重报告。

当输入的表达式为1+2+3 与3+1+2时,截图如下:其中第一,二行为1+2+3的后缀表达式和查重表达式,第三,四行为3+1+2的后缀表达式和查重表达式。

第五行为查重结果,余下的为查重报告。

当输入的表达式为(1+2)*3+5  与3*(1+2) +5 时,截图如下:其中第一,二行为(1+2)*3+5的后缀表达式和查重表达式,第三,四行为3*(1+2) +5 的后缀表达式和查重表达式。

第五行为查重结果,余下的为查重报告

五、psd个人过程:

六、小结.

  1.其实个人认为查重的没什么实际应用的必要,无论查重用什么实现,不管是用二叉树还是本文所采用的后缀转换查重表达式,时间复杂度均在n平方左右,更不用说用于存储二叉树或者查重表达式的所消耗的存储空间里,并且,假设是生成10个表达式,且运算操作数的范围为10,生成两个重复的表达式的概率在接近千分之一,几乎是不可能的。

  2.测试驱动开发的模式很好用。

  3.在需求分析和设计上应该投入更多的时间,前期设计时并没有考虑查重应用导致后期若想采用二叉树代价略高,只能采用查重表达式的方式,其实现在想想比较好的处理方法应该是采用二叉树的数据结构方式去生成表达式,去计算表达式,去查重表达式,若只在查重阶段采用二叉树,则代价太高。

java实现四则运算应用(基于控制台)的更多相关文章

  1. 教你如何使用Java手写一个基于链表的队列

    在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...

  2. JAVA验证码识别:基于jTessBoxEditorFX和Tesseract-OCR训练样本

    JAVA验证识别:基于jTessBoxEditorFX和Tesseract-OCR训练样本 工具准备: jTessBoxEditorFX下载:https://github.com/nguyenq/jT ...

  3. Java五子棋小游戏(控制台纯Ai算法)

    Java五子棋小游戏(控制台纯Ai算法) 继续之前的那个五子棋程序 修复了一些已知的小Bug 这里是之前的五子棋程序 原文链接 修复了一些算法缺陷 本次增加了AI算法 可以人机对战 也可以Ai对Ai看 ...

  4. 编写Java程序,实现从控制台输入对应个数的整数,输出对输入整数的从大到小显示

    编写Java程序,实现从控制台输入对应个数的整数,输出对输入整数的从大到小显示 效果如下: 实现代码: import java.util.Arrays; import java.util.Scanne ...

  5. 个人作业1——四则运算题目生成程序(java代码,基于控制台)

    一.题目描述: 从<构建之法>第一章的 "程序" 例子出发,像阿超那样,花二十分钟写一个能自动生成小学四则运算题目的命令行 "软件",满足以下需求: ...

  6. 四则运算程序(java基于控制台)

    四则运算题目生成程序(基于控制台) 一.题目描述: 1. 使用 -n 参数控制生成题目的个数,例如 Myapp.exe -n 10 -o Exercise.txt 将生成10个题目. 2. 使用 -r ...

  7. 结对编程——paperOne基于java的四则运算 功能改进

    项目成员:张金生     张政 由于新的需求,原本使用JSP的实现方式目前改为Java实现,即去除了B/S端. 需求分析: 1.四则运算要满足整数运算.分数运算两种: 2.运算题目随机,并且可以打印题 ...

  8. 四则运算题目生成程序(基于控制台)(Bug修改)

    针对上个程序中出现的bug进行修改 https://git.coding.net/cx873230936/calculator.git Bug: 1.控制台输入问题数问题 a.不能处理用户输入负数. ...

  9. 【java爬虫】---爬虫+基于接口的网络爬虫

    爬虫+基于接口的网络爬虫 上一篇讲了[java爬虫]---爬虫+jsoup轻松爬博客,该方式有个很大的局限性,就是你通过jsoup爬虫只适合爬静态网页,所以只能爬当前页面的所有新闻.如果需要爬一个网站 ...

随机推荐

  1. rest_framework视图和组件

    一.视图 1.基本视图 #基本视图 #抽取基类 from rest_framework.response import Response from rest_framework.views impor ...

  2. POJ 2774 Long Long Message (二分 + Hash 求最长公共子串)题解

    题意:求最长公共子串 思路:把两个串Hash,然后我们把短的作为LCS的最大可能值,然后二分长度,每次判断这样二分可不可以.判断时,先拿出第一个母串所有len长的子串,排序,然后枚举第二个母串len长 ...

  3. Mock.js 虚拟接口 数据模拟

    Mock.js 是一款前端开发中拦截Ajax请求再生成随机数据响应的工具.可以用来模拟服务器响应. 优点是非常简单方便, 无侵入性, 基本覆盖常用的接口数据类型. 大概记录下使用过程, 详细使用可以参 ...

  4. CSS布局学习(三) - position属性定义及解释(官网直译)

    static ①元素的位置是在文档正常布局流中的位置. ②设置top right bottom left与z-index无效. ③在未指定position时,static是默认值 以下例子进行说明: ...

  5. 剑指offer 02:替换空格

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 解题代码 public cla ...

  6. mongodb笔记(三)

    1.删除文档(remove()函数) 在执行remove()函数前先执行find()命令来判断执行的条件是否正确,这是一个比较好的习惯. 语法: db.collection.remove( <q ...

  7. zend cache使用

    require_once 'Zend/Cache.php';//引用文件$frontendOptions = array( 'lifeTime' => 60, // cache lifetime ...

  8. tomcat服务器-谷歌等浏览器-加载本地图片等资源-报not allowed to load local resource的错误解决办法。

    把文件存放路径目录映射到tomcat中,方法如下: 1.找到tomcat的配置文件(\conf\server.xml)并打开 2.在[host]与[/host]之间加入如下代码:[<Contex ...

  9. Runtime-消息发送和消息转发

    消息发送 消息发送举例:下面这个OC代码 [person read:book]; 会被编译成: objc_msgSend(person, @selector(read:), book); objc_m ...

  10. python报错函数传参数传多了

    写python的时候报错: Exception : Traceback (most recent call last): File , in __bootstrap_inner self.run() ...