java实现小学生四则运算
GitHub地址:https://github.com/TaoTaoLv1/arithmetic
结对伙伴:叶文涛
项目要求:
实现一个自动生成小学四则运算题目的命令行程序.
- 使用 -n 参数控制生成题目的个数(完成)
- 使用 -r 参数控制题目中数值的范围, 。该参数可以设置为1或其他自然数。(完成)
- 生成的题目中计算过程不能产生负数(完成)
- 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。(完成)
- 程序一次运行生成的题目不能重复,生成的题目存入执行程序的当前目录下的Exercises.txt文件(完成)
- 每道题目中出现的运算符个数不超过3个(完成)
- 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件(完成)
- 程序应能支持一万道题目的生成。(完成)
- 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计。(完成)
设计:
分为两个部分,第一是生成题目,生成表达式及答案后写入当前目录下的文件,第二是判断答案是否正确,读取文件后判断,再将结果写入当前目录下的文件。
代码
主函数
public static void main(String[] args){ System.out.println("请选择功能:");
System.out.println(" 1. 四则运算生成器");
System.out.println(" 2. 答案对比");
System.out.print("请输入你的选择[1/2]:");
int choose = new Scanner(System.in).nextInt(); switch (choose){
case 1:
ProducerController producerController = new ProducerController();
producerController.ConstructProblem();break;
case 2:
JudgeAnswerController judgeAnswerController = new JudgeAnswerController();
judgeAnswerController.start();break;
default:
System.out.println("输入不正确,请输入1或2");main(args);break;
}
}
整数生成器与真分数生成器函数
public String[] createProblem(int range){
Random random = new Random();
int operatorCount = 1 + random.nextInt(3); //随机操作符的个数(1-3个)
int operand[] = new int[operatorCount + 1]; //操作数个数
int[] operatorIndex = index(operatorCount, 4, random); for(int i = 0; i < operatorCount + 1; i++){
operand[i] = random.nextInt(range);
} String formula = stitchingFormula(operatorCount, operand, operatorIndex); //计算结果
Calculator calculator = new Calculator();
int res = calculator.algorithm(formula);
String formulaRes[] = new String[2]; if (res > 0){
formulaRes[0] = formula;
formulaRes[1] = String.valueOf(res);
}else {
return createProblem(range);
}
return formulaRes;
}
public String[] createProblem(int range){
Random random = new Random();
int operatorCount = 1 + random.nextInt(3); //操作符的个数1-3 CreateInteger create = new CreateInteger();
int[] operatorIndex = create.index(operatorCount,2, random); //操作符的下标 //生成第一个操作数
int[] coprimeNumber1 = createCoprimeNumbers(range, random);
int x = coprimeNumber1[0];
int y = coprimeNumber1[1]; String s = shamToProperFraction(x, y); for(int i=0; i < operatorCount; i++){
//生成剩下的操作数
int[] coprimeNumber = createCoprimeNumbers(range, random);
int numx = coprimeNumber[0];
int numy = coprimeNumber[1]; String currentOpreator = OPERATOR[operatorIndex[i]]; if(currentOpreator.equals("+")){ //加法
x = x * numy + y * numx;
y = y * numy;
}else { //减法
int count = 0;
while(x * numy - y * numx < 0){ //差为负数
coprimeNumber = createCoprimeNumbers(range, random);
numx = coprimeNumber[0];
numy = coprimeNumber[1];
count++;
if (count >= 5){
numx = x - 1;
numy = y;
}
}
x = x * numy - y * numx;
y = y * numy;
} String num = shamToProperFraction(numx, numy);
s += currentOpreator + num;
} int greatFactor = greatFactor(x,y);
x /= greatFactor; //最终结果化简
y /= greatFactor; String res = shamToProperFraction(x, y);
s += "="; String formulaRes[] = {s, res};
return formulaRes;
} /**
* 假分数转化为真分数
* @param x 分子
* @param y 分母
* @return
*/
public String shamToProperFraction(int x, int y){
if (x > y){
int n = x / y;
x = (x - n * y);
if (x == 0){
return String.valueOf(n);
}
return n + "'" + x + "/" + y;
}else if (x == y){
return "1";
}else if (y == 1){
return String.valueOf(x);
}else if (x == 0){
return "0";
}
return x + "/" + y;
}
}
计算结果函数
public int algorithm(String s) {
Stack<Integer> numStack = new Stack<>(); //放数字
Stack<String> operatorStack = new Stack<>(); //放操作符
HashMap<String, Integer> hashMap = new HashMap<>(); //存放运算符优先级
hashMap.put("(", 0);
hashMap.put("+", 1);
hashMap.put("-", 1);
hashMap.put("*", 2);
hashMap.put("÷", 2); String formula = s.replaceAll(" ", ""); for (int i = 0; i < formula.length();) {
StringBuilder digit = new StringBuilder(); //StringBuilder类中的方法主要偏重于对于字符串的变化,例如追加、插入和删除等,这个也是StringBuffer和String类的主要区别。
char c = formula.charAt(i); //将式子字符串切割为c字符
while (Character.isDigit(c)) { //判断字符是否为10进制数字,将一个数加入digit
digit.append(c);
i++;
if (i < formula.length()){
c = formula.charAt(i);
}else {
break;
}
}
if (digit.length() == 0){ //当前digit里面已经无数字,即当前处理符号
switch (c) {
case '(': {
operatorStack.push(String.valueOf(c));//如果是( 转化为字符串压入字符栈
break;
}
case ')': { //遇到右括号了计算,因为(的优先级最高
String stmp = operatorStack.pop(); //如果是),将符号栈栈顶元素取到
while (!operatorStack.isEmpty() && !stmp.equals("(")) { //当前符号栈里面还有+ - * /
int a = numStack.pop(); //取操作数a,b
int b = numStack.pop();
int result = calculate(b, a, stmp); //计算
if(result < 0)
return -1;
numStack.push(result); //将结果压入栈
stmp = operatorStack.pop(); //符号指向下一个计算符号
}
break;
}
case '=': { //遇到等号了计算
String stmp;
while (!operatorStack.isEmpty()) { //当前符号栈里面还有+ - * /,即还没有算完
stmp = operatorStack.pop();
int a = numStack.pop();
int b = numStack.pop();
int result = calculate(b, a, stmp);
if(result < 0)
return -1;
numStack.push(result);
}
break;
}
default: { //不满足之前的任何情况
String stmp;
while (!operatorStack.isEmpty()) { //如果符号栈有符号
stmp = operatorStack.pop(); //当前符号栈,栈顶元素
if (hashMap.get(stmp) >= hashMap.get(String.valueOf(c))) { //比较优先级
int a = numStack.pop();
int b = numStack.pop();
int result =calculate (b, a, stmp);
if(result < 0)
return -1;
numStack.push(result);
}
else {
operatorStack.push(stmp);
break;
} }
operatorStack.push(String.valueOf(c)); //将符号压入符号栈
break;
}
}
}
else { //处理数字,直接压栈
numStack.push(Integer.valueOf(digit.toString())); //Integer.valueof()返回的是Integer对象,而Integer.parseInt()返回的是int型
continue; //结束本次循环,回到for语句进行下一次循环,即不执行i++(因为此时i已经指向符号了)
}
i++;
}
return numStack.peek(); //返回栈底数字即等式的答案。
}
判断结果函数
public void start(){
System.out.print("请输入待验证答案路径:");
Scanner scanner = new Scanner(System.in);
String exerciseFilePath = scanner.next();
System.out.print("请输入程序生成答案文件路径:");
String answerFilePath = scanner.next(); try {
List<String> exerciseAnswers = exerciseFileReader(exerciseFilePath);
List<String> answers = answerReader(answerFilePath); List<String> correct = new ArrayList<>();
List<String> wrong = new ArrayList<>(); int max = Math.max(exerciseAnswers.size(), answers.size());
int num = 1;
for (int i = 0; i < max; i++){
if (exerciseAnswers.get(i).equals(answers.get(i))){
correct.add(String.valueOf(num++));
}else {
wrong.add(String.valueOf(num++));
}
} File grade = new File("Grade.txt");
if (grade.exists()){
grade.delete();
}
if (grade.createNewFile()){
FileOutputStream gradeOutput = new FileOutputStream(grade);
PrintStream gradePrintStream = new PrintStream(gradeOutput);
String corrects = String.join(",", correct);
gradePrintStream.println("Correct:" + correct.size() +
" (" + corrects + ")");
String wrongs = String.join(",", wrong);
gradePrintStream.println("Wrong:" + wrong.size() +
" (" + wrongs + ")");
} System.out.println("判定完成"); } catch (FileNotFoundException e) {
System.out.println("文件不存在");
} catch (IOException e) {
System.out.println("文件读入异常");
}
} public List<String> exerciseFileReader(String path) throws IOException {
BufferedReader exerciseReader = new BufferedReader(new FileReader(path));
String exerciseAnswer = "";
List<String> exerciseAnswers = new ArrayList<>();
while ((exerciseAnswer = exerciseReader.readLine()) != null){
String[] split = exerciseAnswer.split("=");
if (split[1] != null){
exerciseAnswers.add(split[1]);
}else {
exerciseAnswers.add(" ");
}
}
return exerciseAnswers;
}
测试
1.随机生成10道10以内的四则运算
2.判断题目的正确与否
3.支持生成一万道题目
由于题目过多,因此直接在连接中打开
以上就是所有功能的测试
PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
10 |
5 |
· Estimate |
· 估计这个任务需要多少时间 |
800 |
1200 |
Development |
开发 |
480 |
630 |
· Analysis |
· 需求分析 (包括学习新技术) |
60 |
30 |
· Design Spec |
· 生成设计文档 |
60 |
80 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
30 |
45 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
30 |
30 |
· Design |
· 具体设计 |
30 |
60 |
· Coding |
· 具体编码 |
120 |
360 |
· Code Review |
· 代码复审 |
30 |
45 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
120 |
120 |
Reporting |
报告 |
120 |
120 |
· Test Report |
· 测试报告 |
60 |
30 |
· Size Measurement |
· 计算工作量 |
30 |
30 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
30 |
合计 |
1200 |
1610 |
总结
在这次编程作业中,我和叶文涛同学一起讨论,他主要负责编写代码,后期的测试和报告则由我负责,在这一次的作业中,我也从伙伴身上学习到了很多,认识到自己与他人之间的差距,他在编程过程中也耐心的解答我的疑惑,在这个过程中不断的完善代码。两个人一起处理问题,互相汲取对方好的想法,有些细节没有考虑到的,另一个人可以帮忙补充,这样使得效率也大大提高。例如在我们进行最后测试的过程中,我发现当计算答案时如果答案为空则会出错,在这个情况下我们进行讨论之后也克服了这个问题。
java实现小学生四则运算的更多相关文章
- java的小学生四则运算
import java.awt.*; import java.awt.event.*; import java.io.FileNotFoundException; import java.io.IOE ...
- java小学生四则运算带面板版 但我不知道为什么同类变量却进不了动作监听中去
---恢复内容开始--- package yun; import java.util.*; import java.awt.*; import java.awt.event.ActionEvent; ...
- 3.结对编程成果报告(小学生四则运算的出题程序,Java实现)
程序名称:小学生四则运算的出题程序 先附上代码: package com.makequestion; import java.text.DecimalFormat;import java.util.R ...
- 小学生四则运算出题软件-基于java控制台的实现
.题目描述: 1. 使用 -n 参数控制生成题目的个数,例如 Myapp.exe -n 10 -o Exercise.txt 将生成10个题目. 2. 使用 -r 参数控制题目中数值(自然数.真分数和 ...
- 20175305张天钰Java结对编程四则运算(二)
Java结对编程四则运算(二) 一.题目描述及要求 Git提交粒度不要太粗,建议一个文件/一个类/一个函数/一个功能/一个bug修复都进行提交,不能一天提交一次,更不能一周一次,参考Commit Me ...
- Java实现小学四则运算练习系统(UI)
github项目地址 :https://github.com/feser-xuan/Arithmetic_test3_UI 小伙伴的博客链接:http://www.cnblogs.com/fukang ...
- 作业六:小学生四则运算之NABCD模型与产品Backlog。
NABCD模型与产品Backlog NABCD模型 ) N (Need 需求) 方便了老师和学生,使他们可以想要的时候随时可以得到,省时省力,快速出题,马上得到答案. ) A (Approach 做法 ...
- 30道小学生四则运算题C/C++编程
软件工程科课上,老师通过实例讲解什么是程序,程序和软件的区别,要求我们通过短时间写一道编程题, 题目就是编写30道小学生四则运算题.以下就是源代码: #include<iostream.h> ...
- 20175305张天钰Java结对编程四则运算
Java结对编程四则运算 一.题目描述:如何对表达式进行求值运算呢 1.中缀表达式与后缀表达式(娄老师讲解) 中缀表达式就是运算符号在运算数中间的表达式,比如1+2,顾名思义,后缀表达式就是运算符在运 ...
随机推荐
- 全网最详细的一个超级好用的命令行工具【Cmder】的安装之后的一些配置(图文详解)
不多说,直接上干货! 1.修改命令提示符λ为$ 首先,我们看到 进入解压后的cmder的目录,进入vendor,打开init.bat文件. 修改第15行的代码 @prompt $E[;;40m$P$S ...
- 深入理解 JavaScript 异步系列(1)——基础
前言 2014年秋季写完了<深入理解javascript原型和闭包系列>,已经帮助过很多人走出了 js 原型.作用域.闭包的困惑,至今仍能经常受到好评的留言. 很早之前我就总结了JS三座大 ...
- 【EF6学习笔记】(八)更新关联数据
上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考虑对于有关联的数据进行新增.删除.更新操作:比如Course .Instructor: ...
- 阿里AI设计师一秒出图,小撒连连惊呼,真相是...
近期,央视<机智过人>的舞台上来了位“三超设计师”——设计能力超强:出图能力超快:抗压能力超强,成功迷惑嘉宾和现场观众,更让撒贝宁出错三连. 节目一开场,这位“设计师”就为现场嘉宾:主持人 ...
- Spring mybatis源码篇章-MapperScannerConfigurer关联dao接口
前言:Spring针对Mybatis的XML方式的加载MappedStatement,通过引入MapperScannerConfigurer扫描类来关联相应的dao接口以供Service层调用.承接前 ...
- npm设置和查看仓库源
转载请注明出处:https://www.cnblogs.com/wenjunwei/p/10078460.html 在使用npm命令时,如果直接从国外的仓库下载依赖,下载速度很慢,甚至会下载不下来,我 ...
- centos7安装Wkhtmltopdf
从官网下载预编译版安装: wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12 ...
- xargs原理剖析及用法详解
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 学习这个xargs花了很长时间,在网上翻了很久也查了很多书关于 ...
- devDependencies与dependencies (转载)
简单整理: 一.关键词解释 devDependencies用于本地环境开发 dependencies用户发布环境 devDependencies是只会在开发环境下依赖的模块,生产环境不会被打入包内.通 ...
- 最长滑道问题(非递归,C++)
这是爱奇艺的一道算法题. 题目描述请参考博客http://blog.csdn.net/sinat_30186009/article/details/52356053,在此表示感谢. 基本思路参考了以上 ...