小学生四则运算(java编程)201571030135
任务1源码在Github的仓库主页链接地址:
https://github.com/zhanghh2018/Four-primary-school-pupils
需求分析:
- 作业总体效果:随机产生n道加减乘除练习题;
- 练习题的构成:数字和运算符且每个数字在 0 和 100 之间,运算符在3个到5个之间且每个练习题至少要包含2种运算符;
- 练习题的结果:练习题在运算过程中不出现负数与非整数;
- 最终提交结果:学号与生成的n道练习题及其对应的正确答案;样例如下:

功能设计:
- 表达式的生成模块。首先需要生成运算符与数字,每个等式中运算符的个数加一就等于该等式中的数字个数,之后将生成的符号与数字组合成String,传入逆波兰计算模块进行结果的输出。在此模块中将除法中分母为零的情况、运算符只有一种的情况以及分子分母除不尽的情况排除。
- 表达式的计算模块。利用逆波兰表达式计算结果,在该模块中排除例如30/6/3这样的情况,在之前的模块中排除的只是除号前后的分子分母的情况,并未考虑除号连续的情况,当除号连续时,需要考虑第一个除号运算完之后的结果能否继续除以下一个数的情况,当遇到前后余数不为0的情况以及中间结果为负数的情况就跳出该函数,继续产生新的等式直至满足条件。写这个模块的时候借鉴这位博主的写法(http://blog.csdn.net/u010485491/article/details/51483720);
- 结果写入文件模块。将自己的学号与根据用户输入的题目个数生成的等式写入文件。
- 异常情况的处理。排除输入为非数字的情况以及输入的数字大于1000、小于1以及等于0的情况。
基本功能:
- 实现每道练习题运算符在3个到5个之间,至少要包含2种运算符;
- 运算结果无负数以及非整数;
- 将最终结果保存在文档中以样例为模板;
- 每道练习题的结果不超过一定的范围(考虑到小学生计算能力有限,当时问了郑老师,在老师的提示下,设置了用户输入想要生成结果的范围这一块内容,并进行了异常处理)。
设计实现:
利用Visio进行流程图的绘制,具体流程图如下:其中ContentToTxt(将结果写入文件) Main(主程序可以从命令行接收参数) ReversePolish (逆波兰表达式) RandomEquation(产生等式) result.txt(运行后产生的结果)

测试运行:


核心代码:
1) 随机产生等式模块:为了看起来整洁,去掉了测试过程中注释掉的打印输出部分。等式生成是将生成的数字与运算符依次拼接,之后加上等号构成等式,在构建过程中去除运算符只有一种的情况、分母为0的情况,分子分母有余数的情况。
public class RandomEquation {
public static String randomEquation (){
// Previous expressions
String sBefore = new String();
// The later expression
String sLater = new String();
char[] equation;
int k = 6;
int n;
int m;
int j;
int i;
int[] number;
char[] symbol;
number = new int[k];
symbol = new char[k];
equation = new char[2 * k];
char[] cSymbol = {'+','-','*','÷'};
Random random = new Random();
// Generating operator
for(i = 0;i<(int)(Math.random()*3)+3;i++){
int index = random.nextInt(cSymbol .length);
char resultChar = cSymbol[index];
symbol[i] = resultChar;
}
for(m = 0;m < i;m++){
if(symbol[i - 1] != symbol[m]){
break;
}
}
/*
* Removal of only one operator
* If the last symbol is the same as the previous one, the last one generates a symbol at random.
*/
if(m == i){
do{
int index = random.nextInt(cSymbol.length);
char resultChar = cSymbol[index];
symbol[i - 1] = resultChar;
}while(symbol[i - 1] == symbol[i - 2]);
}
// Generating number
for(j = 0;j < i + 1;j++){
int num = (int)(Math.random()*100);
number[j] = num;
}
// Generating equation
for(n = 0;n < i;n++){
sBefore += String.valueOf(number[n])+String.valueOf(symbol[n]);
}
sBefore += String.valueOf(number[i]);
// Save symbols and numbers into a equation array
for(n = 1;n < 2 * i;n = n+2){
equation[n] = symbol[(n - 1) / 2];
}
for(n = 0;n < 2 * j - 1;n = n+2){
equation[n] = (char)number[(n + 1) / 2];
}
// The removal ÷ denominator is 0 and the molecular denominator is incompatible
for(n = 1;n < i + j && n + 1 < i + j;n = n + 2){
if(equation[n] == '÷'){
if(equation[n + 1]==0){
do{
int num2 = (int)(Math.random()*100);
equation[n + 1] = (char)num2;
}while(equation[n + 1] == 0);
}
else if((int)equation[n - 1] % (int)equation[n + 1]!=0 || (int)equation[n - 1]<(int)equation[n + 1]){
do{
int num2 = (int)(Math.random()*100) + 1;
equation[n + 1] = (char)num2;
if(equation[n + 1] == 0){
do{
int num3 = (int)(Math.random()*100);
equation[n + 1] = (char)num3;
}while(equation[n + 1] == 0);
}
}while((int)equation[n - 1] % (int)equation[n + 1]!= 0 || (int)equation[n - 1]<(int)equation[n + 1]);
}
}
}
// The equation after excluding special circumstances
for(n = 0;n < i+j && n + 1 < i + j;n = n + 2){
sLater += String.valueOf((int)equation[n]);
sLater += String.valueOf(equation[n + 1]);
}
sLater += String.valueOf((int)equation[i + j - 1]);
sLater += String.valueOf('=');
return sLater;
}
}
2)逆波兰模块借鉴这位博主的写法,并在理解的基础上进行了代码的加工。当中间结果小于0或者a%b!=0时,利用return跳出该函数,并在下边的模块中利用返回值进行等式的重新生成。 http://blog.csdn.net/u010485491/article/details/51483720
public static int calcInt(int a, int b, String stmp)
{
int res = 0;
char s = stmp.charAt(0);
switch (s) {
case '+': {
res = a + b;
break;
}
case '-': {
res = a - b;
if(res < 0){
return -1;
}
break;
}
case '*': {
res = a * b;
break;
}
case '÷': {
res = a / b;
if( a % b != 0){
return -1;
}
break;
}
}
return res;
}
3)结果写入文件模块,由于随机产生等式,所以需要一直将该等式保存到字符串里,并对该字符串进行逆波兰求解,否则若随机产生式子randomEquation(),之后又利用ReversePolish(randomEquation()))产生的随机等式的结果,这样会出现等式计算结果与最终运算结果不匹配的情况。在该模块中利用返回值的不同进行结果的保存,若返回值为-1或者大于用户输入的结果值result,就将i的值自减,这样就相当于重新产生符合条件的式子。
for(int i = 0;i < questionAmount;i++){
String randoms = randomEqual.randomEquation();
final boolean existed = reversePolish.reversePolish(randoms) != -1 && reversePolish.reversePolish(randoms) < 500;
if(existed){
contentToTxt.contentToTxt(strFilePath,String.valueOf(randoms+reversePolish.reversePolish(randoms)));
contentToTxt.contentToTxt(strFilePath,String.valueOf("\n"));
}else{
i--;
}
}
总结:
- 在拿到题目的时候,并没有急着去完成代码而是首先进行了需求分析,根据需求分析将本次作业分为三大模块,并对这三个模块进行了功能的划分,每个模块都有要实现的功能,且尽量降低模块之间的联系。以这样的做法书写下来发现思路很清晰,由于不再在一个函数体内书写程序,一个模块出了问题不必全篇找,直接在这个模块中修改即可。
- 由于参加完蓝桥杯之后就没有与java打交道了,一直与c语言打交道,所以java当中的语法也遗忘了不少,使用new这一关键字创建对象也给忘记啦,突然想到一则笑话(甲说都大三了,连女朋友都没有。乙说:new一个‘对象’),这下子就忘不了啦。
- 在书写代码的过程中使用了do while语句,不需要判断循环次数,以前一直在使用while语句,这次在产生表达式的过程中大量使用了do while,深刻体会到了该语句的妙处。
- 在考虑情况的时候并不是一次性完成的,而是在编写代码的过程中慢慢想出来的,到了最后计算结果的时候发现结果已经有上万的啦,所以将输出结果限制在用户要求的范围内,这样就和小学生实际情况相符合。
- 在生成表达式中去除分子分母不能整除的时候,例如a/b/c判断,若a/b不能整除就再随机产生a,b;若同时b/c不能整除则再随机产生b,c;这样下来发现会产生a/b不能整除的情况,因为b随机了两次,后一次随机就无法保证a/b是整数了,所以想到在逆波兰计算的时候进一步排除连续除号除不尽的情况。
- 最后写的是文件模块,由于是将之前写的文档import进去的,在测试是否写好文件的时候发现在目录JRE System Library下边没有产生文件,最后在打开的文件夹中找到了,所以之后的每一次运行就拿Windows自带的记事本打开,明明写了换行符但仍在一行上,测试了好几次都不对,最后和同学交流了才发现这个问题,利用notepad++打开结果就是合适的。
- 本来是想进行附加功能的添加,然而做的时候将一些特殊请款考虑到生成表达式的模块中,导致这些附加功能无法实现,比如真分数的计算,在生成表达式的过程中,将分子分母除不尽的情况已经排除,另外就是加括号的情况,在此模块中将除法中出现的分母为零的情况排除,排除的时候只看除号后边的数字,如果加上括号就没办法进行特殊情况的判断。所以还是在写的时候全盘考虑,不能只想着实现这些基本功能,使得算法没有拓展性。
PSP:
| PSP2.1 | 任务内容 | 计划完成需要的时间(min) | 实际完成需要的时间(min) |
| Planning | 计划 | 20 | 25 |
| Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 20 | 25 |
| Development | 开发 | 360 | 418 |
| Analysis | 需求分析 (包括学习新技术) | 10 | 10 |
| Design Spec | 生成设计文档 | 10 | 8 |
| Design Review | 设计复审 (和同事审核设计文档) | 10 | 15 |
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 20 |
| Design | 具体设计 | 30 | 35 |
| Coding | 具体编码 | 240 | 280 |
| Code Review | 代码复审 | 20 | 25 |
| Test | 测试(自我测试,修改代码,提交修改) | 20 | 25 |
| Reporting | 报告 | 20 | 27 |
| Test Report | 测试报告 | 5 | 5 |
| Size Measurement | 计算工作量 | 5 | 12 |
| Postmortem & Process Improvement Plan | 事后总结 ,并提出过程改进计划 | 10 | 10 |
小学生四则运算(java编程)201571030135的更多相关文章
- 小学生四则运算JAVA
点我,github地址 组员:黄浩格,何坤 一.项目说明 1题目:实现一个自动生成小学四则运算题目的命令行程序. 2说明: 自然数:0, 1, 2, -. • 真分数:1/2, 1/3, 2/3, 1 ...
- 3.结对编程成果报告(小学生四则运算的出题程序,Java实现)
程序名称:小学生四则运算的出题程序 先附上代码: package com.makequestion; import java.text.DecimalFormat;import java.util.R ...
- 30道小学生四则运算题C/C++编程
软件工程科课上,老师通过实例讲解什么是程序,程序和软件的区别,要求我们通过短时间写一道编程题, 题目就是编写30道小学生四则运算题.以下就是源代码: #include<iostream.h> ...
- java小学生四则运算带面板版 但我不知道为什么同类变量却进不了动作监听中去
---恢复内容开始--- package yun; import java.util.*; import java.awt.*; import java.awt.event.ActionEvent; ...
- 作业六:小学生四则运算之NABCD模型与产品Backlog。
NABCD模型与产品Backlog NABCD模型 ) N (Need 需求) 方便了老师和学生,使他们可以想要的时候随时可以得到,省时省力,快速出题,马上得到答案. ) A (Approach 做法 ...
- JAVA编程思想(第四版)学习笔记----4.8 switch(知识点已更新)
switch语句和if-else语句不同,switch语句可以有多个可能的执行路径.在第四版java编程思想介绍switch语句的语法格式时写到: switch (integral-selector) ...
- 《Java编程思想》学习笔记(二)——类加载及执行顺序
<Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...
- #Java编程思想笔记(一)——static
Java编程思想笔记(一)--static 看<Java编程思想>已经有一段时间了,一直以来都把笔记做在印象笔记上,今天开始写博客来记录. 第一篇笔记来写static关键字. static ...
- [Java编程思想-学习笔记]第3章 操作符
3.1 更简单的打印语句 学习编程语言的通许遇到的第一个程序无非打印"Hello, world"了,然而在Java中要写成 System.out.println("He ...
- Java编程思想重点笔记(Java开发必看)
Java编程思想重点笔记(Java开发必看) Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而 ...
随机推荐
- [Swift]LeetCode472. 连接词 | Concatenated Words
Given a list of words (without duplicates), please write a program that returns all concatenated wor ...
- [Swift]LeetCode862. 和至少为 K 的最短子数组 | Shortest Subarray with Sum at Least K
Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K. If there ...
- SQL执行错误#1064---保留字错误
CREATE TABLE IF NOT EXISTS `change` ( `id` INT NOT NULL AUTO_INCREMENT, `creator` VARCHAR(45) NOT NU ...
- Spark中SQL列和并为一行
在使用数据库的时候,需要将查询出来的一列按照逗号合并成一行. 原表名字为 TABLE ,表中的部分原始数据为: +---------+------------------------+ | BASIC ...
- 【从零开始自制CPU之学习篇06】寄存器
上一篇文章学习了总线的相关知识,途中ABC当时假设为一个个的8位寄存器.这一篇要学习怎么构建这个寄存器. 这分为两个三个部分,数据输入,寄存器,数据输出.首先不管输出,来看数据输入和寄存器这两个部分. ...
- C++ 断言
assert宏 (基本概念与用法整理) assert宏的深入学习 1.运行时断言 1.1.assert属于运行时断言,可以在运行时判断给定条件是否为真,如果为真则什么也不做,否则打印一跳错误信息,然后 ...
- qt 坐标变换
原文链接:Qt学习之路(28): 坐标变换 同很多坐标系统一样,QPainter的默认坐标的原点(0, 0)位于屏幕的左上角,X轴正方向是水平向右,Y轴正方向是竖直向下.在这个坐标系统中,每个像素 ...
- CentOs~程序部署那些事
永久更新中…… 主要说一下在centos里,在安装程序和监控程序时,用到的一些常用的命令,希望可以帮到大家! 远程安装程序包:yum install 程序包名 下载程序包:wget 程序包地址 解压t ...
- jaeger 使用初探
导读:有一天我们接到这样一条客诉“你们的收银软件最近特别慢,严重影响我们的收银效率,再不解决我们就不用了”,我相信大家应该都遇到过这种问题,即使现在没遇到,将来一定会遇到的,那遇到了怎么办呢?就这个话 ...
- Unlink——2016 ZCTF note2解析
简介 Unlink是经典的堆漏洞,刚看到这个漏洞不知道如何实现任意代码执行,所以找了一个CTF题,发现还有一些细节的地方没有讲的很清楚,题目在这里.自己也动手写一遍,体验一下 题目描述 首先,我们先分 ...

