GitHub链接:https://github.com/3216004716/four-operations.git

项目相关要求

  1. 使用 -n 参数控制生成题目的个数,例如

    Myapp.exe -n 10 将生成10个题目。

  1. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如

    Myapp.exe -r 10

    将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。

  1. 生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1 − e2的子表达式,那么e1 ≥ e2。

  2. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。

  3. 每道题目中出现的运算符个数不超过3个。

  4. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。

    生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:

    1. 四则运算题目1

    2. 四则运算题目2

    其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。

  1. 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:

    1.答案1

    2.答案2

    特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。

  1. 程序应能支持一万道题目的生成。

  2. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:

    Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt

    统计结果输出到文件Grade.txt,格式如下:

      Correct: 5 (1, 3, 5, 7, 9)

      Wrong: 5 (2, 4, 6, 8, 10)

    其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。

PSP:

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 15
· Estimate · 估计这个任务需要多少时间 10 15
Development 开发 1160 1510
· Analysis · 需求分析 (包括学习新技术) 200 400
· Design Spec · 生成设计文档 60 60
· Design Review · 设计复审 (和同事审核设计文档) 30 20
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 60
· Design · 具体设计 60 90
· Coding · 具体编码 600 700
· Code Review · 代码复审 120 90
· Test · 测试(自我测试,修改代码,提交修改) 60 90
Reporting 报告 120 150
· Test Report · 测试报告 80 90
· Size Measurement · 计算工作量 10 20
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 40
合计   1290 1675

解题思路:

  • 取随机操作数

  • 取随机操作符

  • 生成表达式

  • 由表达式转换为后缀表达式

  • 后缀表达式入栈,计算

  • 去重

  • 结果写入文件

设计实现过程

  • Utils

    • RandomUtil 生成随机操作数和随机操作符

    • ExpressionUtil 生成表达式

    • CalculateUtil 封装计算的方法

    • FileUtil 生成题目和答案的文档

  • Calculate

    • calculateResult 用于计算结果

  • Expression

    • CheckExpression 检查重复的表达式

    • MyExpression 表达式类

    • PostfixExpression 生成后缀表达式

代码说明

  • RandomUtil类 获取随机操作数,用了Math.random()

// 获取随机操作数
public static String getRandomOperand(int range) {
String Operand = null;
int index = (int) (Math.random() * 4);
if (index == 0) {// 生成分数
index = (int) (Math.random() * 3);
if (index == 2) {// 生成假分数
Operand = getImproperTractionNumber(range);
} else {// 生成真分数
Operand = getTruTractionNumber(range);
}
} else {
Operand = getNaturalNumber(range);// 生成整数
}
return Operand;
}
  • ExpressionUtil类 获取随机表达式

public static MyExpression getRandomExpression(int range) {
// 获取随机表达式
MyExpression myExpression = null;
int index = (int) (Math.random() * 10);
if (index <= 3) {
myExpression = getOneOperExp(range);// 一个操作符
} else if (index == 4) {// 三个操作符
index = (int) (Math.random() * 2);
if (index == 0) {
myExpression = getThreeOperExp(range);
} else {
myExpression = getThreeOperExpWithBracket(range);
}
} else {// 两个操作符
index = (int) (Math.random() * 2);
if (index == 0) {
myExpression = getTwoOperExp(range);
} else {
myExpression = getTwoOperExpWithBracket(range);
}
}
CaculateResult.caculate(myExpression); // 计算结果

return myExpression;
}
  • PostfixExpression类 生成后缀表达式

private static ArrayList<String> generatePostfixExpression(String expression) {
//生成String类型的后缀表达式
String[] expressionArray = expression.split(" ");
ArrayList<String> postfixExpression = new ArrayList<String>();
Stack<String> stack = new Stack<String>();
for (int i = 0; i < expressionArray.length; i++) {
String item = expressionArray[i];
String temp = "";
switch (item) {
case "(":
stack.push(item);
break;
case ")":
while ((stack.size() != 0) && !((temp = stack.pop()).equals("("))) {
postfixExpression.add(temp);
}
break;
case "+":
case "-":
while ((stack.size() != 0) && !((temp = stack.pop()).equals("("))) {
postfixExpression.add(temp);
}
if (temp.equals("(")) {
stack.push(temp);
}
stack.push(item);
break;
case "×":
case "÷":
while ((stack.size() != 0) && !((temp = stack.pop()).equals("("))) {
if (temp.equals("×") || temp.equals("÷")) {
postfixExpression.add(temp);
} else {
stack.push(temp);
break;
}
}
if (temp.equals("(")) {
stack.push(temp);
}
stack.push(item);
break;
default:
postfixExpression.add(item);
}
}
while (stack.size() != 0) {
postfixExpression.add(stack.pop());
}
return postfixExpression;
}
  • CalculateResult类 计算后缀表达式

public class CaculateResult {

    public static void caculate(MyExpression myExpression) {
PostfixExpression.toPostfixExpression(myExpression);
ArrayList<String> postfixExpression = myExpression.getPostfixExpression();
String temp = "";
Stack<String> s = new Stack<>(); String rightOperand = null;
String leftOperand = null;
int result = 0;
int a1, a2, b1, b2 = 0;
int denominator = 0;
int numerator = 0;
a: for (int i = 0; i < postfixExpression.size(); i++) { String item = postfixExpression.get(i);
switch (item) {
case "+":
rightOperand = s.pop();
leftOperand = s.pop();
if (CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
result = Integer.parseInt(rightOperand) + Integer.parseInt(leftOperand);
temp = String.valueOf(result);
} else if (CaculateUtil.isNumeric(rightOperand) && !CaculateUtil.isNumeric(leftOperand)) {
denominator = CaculateUtil.getDenominator(leftOperand);
numerator = CaculateUtil.getNumerator(leftOperand);
numerator = Integer.parseInt(rightOperand) * denominator + numerator;
temp = numerator + "/" + denominator;
} else if (!CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
denominator = CaculateUtil.getDenominator(rightOperand);
numerator = CaculateUtil.getNumerator(rightOperand);
numerator = Integer.parseInt(leftOperand) * denominator + numerator;
temp = numerator + "/" + denominator;
} else {
a1 = CaculateUtil.getDenominator(rightOperand);
a2 = CaculateUtil.getNumerator(rightOperand);
b1 = CaculateUtil.getDenominator(leftOperand);
b2 = CaculateUtil.getNumerator(leftOperand);
numerator = a1 * b2 + a2 * b1;
denominator = a1 * b1;
temp = numerator + "/" + denominator;
}
s.push(temp);
break; case "×":
rightOperand = s.pop();
leftOperand = s.pop();
if (CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
result = Integer.parseInt(rightOperand) * Integer.parseInt(leftOperand);
temp = String.valueOf(result);
} else if (CaculateUtil.isNumeric(rightOperand) && !CaculateUtil.isNumeric(leftOperand)) {
numerator = CaculateUtil.getNumerator(leftOperand);
denominator = CaculateUtil.getDenominator(leftOperand);
numerator = numerator * Integer.parseInt(rightOperand);
temp = numerator + "/" + denominator;
} else if (!CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
numerator = CaculateUtil.getNumerator(rightOperand);
denominator = CaculateUtil.getDenominator(rightOperand);
numerator = numerator * Integer.parseInt(leftOperand);
temp = numerator + "/" + denominator;
} else {
a1 = CaculateUtil.getDenominator(rightOperand);
a2 = CaculateUtil.getNumerator(rightOperand);
b1 = CaculateUtil.getDenominator(leftOperand);
b2 = CaculateUtil.getNumerator(leftOperand);
numerator = a2 * b2;
denominator = a1 * b1;
temp = numerator + "/" + denominator;
}
s.push(temp);
break; case "-":
leftOperand = s.pop();
rightOperand = s.pop();
int inta, intb = 0;
if (CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
inta = Integer.parseInt(rightOperand);
intb = Integer.parseInt(leftOperand);
result = inta - intb;
temp = String.valueOf(result);
} else if (CaculateUtil.isNumeric(rightOperand) && !CaculateUtil.isNumeric(leftOperand)) {
inta = Integer.parseInt(rightOperand);
numerator = CaculateUtil.getNumerator(leftOperand);
denominator = CaculateUtil.getDenominator(leftOperand);
numerator = inta * denominator - numerator;
temp = numerator + "/" + denominator;
} else if (!CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
intb = Integer.parseInt(leftOperand);
numerator = CaculateUtil.getNumerator(rightOperand);
denominator = CaculateUtil.getDenominator(rightOperand);
numerator = numerator - intb * denominator;
temp = numerator + "/" + denominator;
} else {
a1 = CaculateUtil.getDenominator(rightOperand);
a2 = CaculateUtil.getNumerator(rightOperand);
b1 = CaculateUtil.getDenominator(leftOperand);
b2 = CaculateUtil.getNumerator(leftOperand);
numerator = a2 * b1 - a1 * b2;
denominator = a1 * b1;
temp = numerator + "/" + denominator;
}
if (temp.contains("-")||temp.equals("0")) {
myExpression.setCheckAnswer(false);
break a;
}
s.push(temp);
break; case "÷":
leftOperand = s.pop();
rightOperand = s.pop();
int integer_a = 0, integer_b = 0;
if (CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
integer_a = Integer.parseInt(rightOperand);
integer_b = Integer.parseInt(leftOperand);
if (integer_b == 0) {
break;
} else if ((integer_a % integer_b) == 0) {
result = integer_a / integer_b;
temp = String.valueOf(result);
} else {
numerator = integer_a;
denominator = integer_b;
temp = numerator + "/" + denominator;
}
} else if (CaculateUtil.isNumeric(rightOperand) && !CaculateUtil.isNumeric(leftOperand)) {
integer_a = Integer.parseInt(rightOperand);
numerator = CaculateUtil.getNumerator(leftOperand);
denominator = CaculateUtil.getDenominator(leftOperand);
int temp1 = numerator;
numerator = integer_a * denominator;
denominator = temp1;
temp = numerator + "/" + denominator;
} else if (!CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
integer_b = Integer.parseInt(leftOperand);
numerator = CaculateUtil.getNumerator(rightOperand);
denominator = CaculateUtil.getDenominator(rightOperand);
denominator = denominator * integer_b;
temp = numerator + "/" + denominator;
} else {
a1 = CaculateUtil.getDenominator(rightOperand);
a2 = CaculateUtil.getNumerator(rightOperand);
b1 = CaculateUtil.getDenominator(leftOperand);
b2 = CaculateUtil.getNumerator(leftOperand);
numerator = a2 * b1;
denominator = a1 * b2;
temp = numerator + "/" + denominator;
}
s.push(temp);
break; default:
s.push(item);
break;
}
}
myExpression.setResult(CaculateUtil.reduceFractiong(temp));
}
}
  • CheckExpression类 检查重复的表达式

public class CheckExpression {

public static boolean checkRepeated(MyExpression expression1, MyExpression expression2) {
boolean flag = true;
if (expression1.getPostfixExpression().size() == expression2.getPostfixExpression().size()) {
if (expToString(expression1.getPostfixExpression()).equals(expToString(expression2.getPostfixExpression()))
|| changePosition(expression1).equals(expToString(expression2.getPostfixExpression()))) {
flag = false;
}
}
return flag;
}

static String changePosition(MyExpression expression) {
ArrayList<String> postfixExpression = expression.getPostfixExpression();
String firstOperator = getFirstOperator(postfixExpression);
if (firstOperator.equals("+") || firstOperator.equals("×")) {
int index = postfixExpression.indexOf(firstOperator);
String temp = postfixExpression.get(index - 1);
postfixExpression.set(index - 1, postfixExpression.get(index - 2));
postfixExpression.set(index - 2, temp);
}

return expToString(postfixExpression);
}

static String getFirstOperator(ArrayList<String> postfixExpression) {
String operator = "";
for (int i = 0; i < postfixExpression.size(); i++) {
String item = postfixExpression.get(i);
if (item.equals("+") || item.equals("-") || item.equals("×") || item.equals("÷")) {
operator = item;
break;
}
}
return operator;
}

public static String expToString(ArrayList<String> PostfixExpression) {
String string = null;
for (int i = 0; i < PostfixExpression.size(); i++) {
string += PostfixExpression.get(i);
}
return string;
}
}

运行结果

项目小结

  • 谢雅淇:我觉得这次程序的编写,我只是在为了解决问题而写方法的代码,没有很好地融入面向对象的思想。还有在写代码之前就要把思路理清楚,不然代码就会写的很乱,不仅会浪费时间,还会把代码写得非常冗长,可观性比较差。这次作业的结对队友,从讨论需求到编写代码的过程中都帮助了我很多,我觉得我需要提升的地方还有很多,以后还需要继续努力,多加练习。

  • 袁杏仪:我觉得这次程序的编写,让我对开发程序有了更深入的了解,体会到沟通与合作的重要性,同时也感受到团队开发的乐趣,还收获了真挚的友谊。这次作业,让我感触最深的是我们写完代码后测试时,得出结果然后进行验算,检查出错答案并对源代码进行修改的过程,每一次修改,一步步得出正确的结果,这让我非常有成就感。

Java实现四则运算 谢雅淇 袁杏仪的更多相关文章

  1. 四则运算 Java (于泽浩,袁浩越)

    GitHub 地址 一. 项目要求 题目 实现一个自动生成小学四则运算题目的命令行程序. 需求(全部完成) 使用 -n 参数控制生成题目的个数 Myapp.exe -n 10 使用 -r 参数控制题目 ...

  2. Java实现四则运算,使用堆栈,检查语法

    突然发闲想试一试自己实现算术的四则运算,支持加减乘除和括号.正负号:支持语法检查:思路很常规,利用两个堆栈,一个压操作符,一个压操作数,念头冒出来之后,立马动手:然后本以为很容易的一个实现,却存在各种 ...

  3. 结对编程1----基于java的四则运算生成器

    小组成员:王震(201421123054).王杰(201421123055) Coding地址:https://git.coding.net/a506504661/sssss.git 一.题目描述 我 ...

  4. java重构四则运算

    package 重构四则运算; import java.io.IOException; public class Test { public static void main(String[] arg ...

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

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

  6. java小学生四则运算带面板版 但我不知道为什么同类变量却进不了动作监听中去

    ---恢复内容开始--- package yun; import java.util.*; import java.awt.*; import java.awt.event.ActionEvent; ...

  7. 如何实现java的四则运算

    很多语言底层对四则运算都有内部封装, 我们还是要重复造下轮子,不为别的, 就是为了面试可以多装一分 b, 假设你已经了解了什么是二进制, 什么是异或, 什么是移位运算, 什么是与, 这些不懂就别硬上( ...

  8. JAVA实现四则运算的简单计算器

    开发环境eclipse java neon. 今天用JAVA的swing界面程序设计制作了一个四则运算的简易计算器.代码以及截图如下: computer.java: ///////////////// ...

  9. Java 执行四则运算

    四种基本的操作原理是将被转换成后缀缀表达式表达.然后计算. 转换思路和原则.可以参考将中缀表达式转化为后缀表达式 import java.math.BigDecimal; import java.ut ...

随机推荐

  1. form表单中name和id区别

    HTML文本是由HTML命令组成的描述性文本,HTML命令可以说明文字.图形.动画.声音.表格.链接等.HTML的结构包括头部(Head).主体(Body)两大部分,其中头部描述浏览器所需的信息,而主 ...

  2. dubbox下载编译运行demo

    最近公司要搞微服务改造,拿了一个小项目开刀,找来找去,还是偏向当当的dubbox作为分布式服务框架.这里介绍下怎么一条龙跑起一个demo. 1.下载代码 因为代码放在github上,所以我们直接用Ec ...

  3. Go基本语句

    递增递减语句 在GO中,++与--是作为语句而并不是作为表达式 package main import "fmt" func main() { a:= //a=a++ //语句而非 ...

  4. 【转】使用JMeter进行负载测试——终极指南

    使用JMeter进行负载测试——终极指南 这篇教程讨论的是JMeter,它是一款基于Java的.集合了几个应用程序.具有特定用途的负载和性能测试工具. 本篇主要涉及的内容: 解释一下JMeter的用途 ...

  5. __CLASS__

    <?php class base_class { function say_a() { echo "'a' - said the " . __CLASS__ . " ...

  6. python开发函数进阶:命名空间,作用域,函数的本质,闭包,作用域方法(globales)

    一,命名空间 #局部命名空间#全局命名空间#内置命名空间 #三者的顺序#加载顺序       内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程 ...

  7. tomcat 1字节的UTF-8序列的字节1无效

    微信支付时, 命名返回支付成功, 但是成功后却返回如下的错误, 在测试环境都是没有任何问题, 到客户现场后, 可能客户现场使用的4G网络, 用微信支付时一直报这样的错误 错误现象: com.sun.o ...

  8. FPGA SD 卡 之 乒乓操作 、同步fifo

    这里记录一个实际的需要使用乒乓操作的例子:读sd卡数据的时,在spi的模式下.发送单数据块的读取命令,在回应之后会有 512字节的数据.使用乒乓操作,可以用两个八位的寄存器,就可以完成连续的512字节 ...

  9. gevent实现套接字

    server------------- #!/usr/bin/env python # encoding: utf-8  # Date: 2018/6/17 from gevent import mo ...

  10. Deep Learning 学习笔记(4):Logistic Regression 逻辑回归

    逻辑回归主要用于解决分类问题,在现实中有更多的运用, 正常邮件or垃圾邮件 车or行人 涨价or不涨价 用我们EE的例子就是: 高电平or低电平 同时逻辑回归也是后面神经网络到深度学习的基础. (原来 ...