四则运算 Java 杨辉鹏,郑冠华
四则运算 Java 杨辉鹏,郑冠华
GitHub链接:https://github.com/yanghuipeng/arithmetic
项目相关要求
使用 -n 参数控制生成题目的个数,例如
-n 10 将生成10个题目。
使用 -r 参数控制题目中数值(自然数、真分数)的范围,例如
-r 10
将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。
生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1 − e2的子表达式,那么e1 ≥ e2。
生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。
每道题目中出现的运算符个数不超过3个。
程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。
生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:
四则运算题目1
四则运算题目2
其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。
在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:
1.答案1
2.答案2
特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。
程序应能支持一万道题目的生成。
程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:
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
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
30 | 50 |
· Estimate |
· 估计这个任务需要多少时间 |
30 | 50 |
Development |
开发 |
1100 | 2260 |
· Analysis |
· 需求分析 (包括学习新技术) |
80 | 180 |
· Design Spec |
· 生成设计文档 |
60 | 100 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
30 | 40 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
30 | 30 |
· Design |
· 具体设计 |
100 | 150 |
· Coding |
· 具体编码 |
600 | 1500 |
· Code Review |
· 代码复审 |
50 | 60 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
150 | 200 |
Reporting |
报告 |
80 | 80 |
· Test Report |
· 测试报告 |
30 | 40 |
· Size Measurement |
· 计算工作量 |
20 | 20 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 | 20 |
合计 |
1210 | 2390 |
解题思路:
生成随机操作数
取随机操作符
生成表达式
- 计算
判重
结果写入文件
设计实现过程
Fraction分数类定义一个分数及分数的基本操作
- Expression表达式类定义一个表达式及计算表达式的结果
Function输出功能类输出结果
代码
项目目录:
主函数:(启动程序)Main.java
package TwoProject; import java.io.*;
import java.util.Scanner; public class Main { public static void main(String[] args) throws IOException {
// TODO 自动生成的方法存根
int titleNum; // 定义题目个数
int parameterRange; // 定义参数范围
System.out.println("**** -n [数值] 使用 -n 参数控制生成题目的个数");
System.out.println("**** -e <exercisefile>.txt -a <answerfile>.txt 对给定的题目文件和答案文件,判定答案中的对错并进行数量统计");
System.out.print("请输入命令:");
Scanner s = new Scanner(System.in);
String m = s.nextLine();
String str[] = m.split("\\s");
switch (str[0]) {
case "-n":
titleNum = Integer.valueOf(str[1].toString());
System.out.println("**** -r [数值] 使用 -r 参数控制题目中数值(自然数、真分数)的范围(数值应大于1)");
System.out.print("请输入命令:");
Scanner ss = new Scanner(System.in);
String n = ss.nextLine();
String strr[] = n.split("\\s");
if (strr[0].equals("-r")) {
parameterRange = Integer.valueOf(strr[1].toString());
Function function = new Function(titleNum, parameterRange);
function.outputExercises();
break;
} else {
System.out.println("输入的命令有误!");
break;
}
case "-e":
Function function0 = new Function();
String gradePath = "Grade.txt";
function0.outputGrade(str[1], str[3], gradePath);
break;
default:
System.out.println("输入的命令有误!");
break;
}
s.close(); } }
分数类 Fraction
package TwoProject; public class Fraction { private int a; // 定义分子
private int b; // 定义分母 public Fraction(String string) { // 将数字的字符串形式转换为整数、分数形式
string = string.trim(); // 清除前后空格
int c = string.indexOf("'"); // 求带分数标志“'”的索引
int d = string.indexOf("/"); // 求分数标志“/”的索引
if (c != -1) { // 数字为带分数
int z = Integer.valueOf(string.substring(0, c));
b = Integer.valueOf(string.substring(d + 1));
a = z * b + Integer.valueOf(string.substring(c + 1, d));
} else if (d != -1) { // 数字为真分数
b = Integer.valueOf(string.substring(d + 1));
a = Integer.valueOf(string.substring(0, d));
} else { // 数字为整数
a = Integer.valueOf(string);
b = 1;
}
build(a, b);
} public Fraction(int a, int b) {
build(a, b);
} // 数字形式转换为字符串形式
public String toString() {
if (b == 1) {
return String.valueOf(a);
} else {
int i = a / b;
if (i != 0) {
return String.format("%d'%d/%d", i, a - b * i, b);
} else {
return String.format("%d/%d", a, b);
}
}
} // 给定分子分母构造分数
private void build(int a, int b) {
if (b == 0) {
throw new RuntimeException("分母不能为0");
}
int c = comfactor(a, b);
this.a = a / c;
this.b = b / c;
} // 求公因子
private int comfactor(int a, int b) {
int mod = a % b;
return mod == 0 ? b : comfactor(b, mod);
} // 加法 a + b
public Fraction add(Fraction fraction) {
return new Fraction(this.a * fraction.b + fraction.a * this.b, this.b * fraction.b);
} // 减法 a - b
public Fraction subtraction(Fraction fraction) {
return new Fraction(this.a * fraction.b - fraction.a * this.b, this.b * fraction.b);
} // 乘法 a x b
public Fraction multiplication(Fraction fraction) {
return new Fraction(this.a * fraction.a, this.b * fraction.b);
} // 除法a/b
public Fraction division(Fraction fraction) {
return new Fraction(this.a * fraction.b, b * fraction.a);
} public double getDouble() {
return a / b;
}
}
表达式类Expression
package TwoProject; import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom; /**
*
* @author 辉鹏
* @param parameterRange
* 参数范围
*
*
*/
public class Expression {
int parameterRange;
char[] symbol = { '+', '-', '×', '÷' };
boolean isWrong = false;
String s;
ThreadLocalRandom random = ThreadLocalRandom.current();
public Expression(String string) {
s=string.trim();
expreGenerate(s);
}
public Expression(int parameterRange) {
super();
this.parameterRange = parameterRange;
int n = random.nextInt(1, 4);
char[] symchar = new char[n];
char[] symchar1 = new char[n];
for (int i = 0; i < n; i++) {
int j = random.nextInt(0, 4);
symchar[i] = symbol[j];
}
for (int i = 0; i < n; i++) {
if (symchar[i] == '+' || symchar[i] == '-') {
symchar1[i] = '1';
}
if (symchar[i] == '×' || symchar[i] == '÷') {
symchar1[i] = '2';
}
}
String string = symchar1.toString().trim();
if (n == 1) {
String[] str0 = new String[4];
str0[0] = createFraction().toString();
str0[1] = String.valueOf(symchar[0]);
str0[2] = createFraction().toString();
str0[3] = "=";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 4; i++) {
stringBuffer = stringBuffer.append(str0[i] + " ");
}
s = stringBuffer.toString();
} else if (n == 2) {
if (string == "12" || string == "22") {
Object[] str1 = new String[6];
str1[0] = createFraction().toString();
str1[1] = String.valueOf(symchar[0]);
str1[2] = createFraction().toString();
str1[3] = String.valueOf(symchar[1]);
str1[4] = createFraction().toString();
str1[5] = "=";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 6; i++) {
stringBuffer = stringBuffer.append(str1[i] + " ");
}
s = stringBuffer.toString();
} else {
String[] str2 = new String[8];
str2[0] = createFraction().toString();
str2[1] = String.valueOf(symchar[0]);
str2[2] = "(";
str2[3] = createFraction().toString();
str2[4] = String.valueOf(symchar[1]);
str2[5] = createFraction().toString();
str2[6] = ")";
str2[7] = "=";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 8; i++) {
stringBuffer = stringBuffer.append(str2[i] + " ");
}
s = stringBuffer.toString();
}
} else {
if (string == "221" || string == "222") {
String[] str3 = new String[10];
str3[0] = createFraction().toString();
str3[1] = String.valueOf(symchar[0]);
str3[2] = createFraction().toString();
str3[3] = String.valueOf(symchar[1]);
str3[4] = "(";
str3[5] = createFraction().toString();
str3[6] = String.valueOf(symchar[2]);
str3[7] = createFraction().toString();
str3[8] = ")";
str3[9] = "=";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 10; i++) {
stringBuffer = stringBuffer.append(str3[i] + " ");
}
s = stringBuffer.toString().trim(); } else if (string == "111" || string == "112") {
Object[] str4 = new String[10];
str4[0] = createFraction().toString();
str4[1] = String.valueOf(symchar[0]);
str4[2] = "(";
str4[3] = createFraction().toString();
str4[4] = String.valueOf(symchar[1]);
str4[5] = createFraction().toString();
str4[6] = ")";
str4[7] = String.valueOf(symchar[2]);
str4[8] = createFraction().toString();
str4[9] = "=";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 10; i++) {
stringBuffer = stringBuffer.append(str4[i] + " ");
}
s = stringBuffer.toString().trim();
} else if (string == "121" || string == "122") {
Object[] str5 = new String[10];
str5[0] = "(";
str5[1] = createFraction().toString();
str5[2] = String.valueOf(symchar[0]);
str5[3] = createFraction().toString();
str5[4] = ")";
str5[5] = String.valueOf(symchar[1]);
str5[6] = createFraction().toString();
str5[7] = String.valueOf(symchar[2]);
str5[8] = createFraction().toString();
str5[9] = "=";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 10; i++) {
stringBuffer = stringBuffer.append(str5[i] + " ");
}
s = stringBuffer.toString().trim();
} else {
Object[] str6 = new String[8];
str6[0] = createFraction().toString();
str6[1] = String.valueOf(symchar[0]);
str6[2] = createFraction().toString();
str6[3] = String.valueOf(symchar[1]);
str6[4] = createFraction().toString();
str6[5] = String.valueOf(symchar[2]);
str6[6] = createFraction().toString();
str6[7] = "=";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 8; i++) {
stringBuffer = stringBuffer.append(str6[i] + " ");
}
s = stringBuffer.toString().trim();
}
}
expreGenerate(s);
} // 随机生成一个分数
Fraction createFraction() {
return new Fraction(random.nextInt(1, parameterRange), random.nextInt(1, 10));
} // 返回一个表达式
private String expreGenerate(String s) {
return s;
} // 表达式计算
private Fraction calculate(String symbol0, Fraction left0, Fraction right0) {
String symbol = symbol0;
Fraction left = left0;
Fraction right = right0;
switch (symbol) {
case "+":
return left.add(right);
case "-":
if (left.getDouble() <= right.getDouble()) {
isWrong = true;
return new Fraction(1, 1);
} else {
return left.subtraction(right);
}
case "×":
return left.multiplication(right);
default:
return left.division(right);
}
} // 表达式结果计算方法
public String getResult() {
String string = s;
String[] strings = string.split("\\s+");
List<String> list = new ArrayList<String>();
for (int i = 0; i < strings.length; i++) {
list.add(strings[i]);
}
if (string.indexOf("(") != -1) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("="))
break;
if (list.get(i).equals("(")) {
list.set(i, calculate(list.get(i + 2), new Fraction(list.get(i + 1)), new Fraction(list.get(i + 3)))
.toString());
for (int j = 0; j < 4; j++) {
list.remove(i + 1);
}
}
}
}
if (string.indexOf("×") != -1 || string.indexOf("÷") != -1) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("="))
break;
if (list.get(i).equals("×") || list.get(i).equals("÷")) {
list.set(i - 1, calculate(list.get(i), new Fraction(list.get(i - 1)), new Fraction(list.get(i + 1)))
.toString());
for (int j = 0; j < 2; j++) {
list.remove(i);
}
i--;
}
}
}
if (string.indexOf("+") != -1 || string.indexOf("-") != -1) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("="))
break;
if (list.get(i).equals("+") || list.get(i).equals("-")) {
list.set(i - 1, calculate(list.get(i), new Fraction(list.get(i - 1)), new Fraction(list.get(i + 1)))
.toString());
for (int j = 0; j < 2; j++) {
list.remove(i);
}
i--;
}
}
}
return list.get(0);
} public String toString() {
return s;
}
}
输出功能类Function
package TwoProject; import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set; /**
* @param titleNum
* 题目个数
* @param parameterRange
* 参数范围
*/
public class Function {
int titleNum;
int parameterRange;
Set<String> set = new HashSet<>(); public Function() { } public Function(int titleNum, int parameterRange) {
this.titleNum = titleNum;
this.parameterRange = parameterRange;
} public void outputExercises() {
try {
PrintWriter exercisesWriter = new PrintWriter(new FileWriter("Exercises.txt"));
PrintWriter answerWriter = new PrintWriter(new FileWriter("Answers.txt"));
for (int i = 1; i < titleNum + 1;) {
Expression expression = new Expression(parameterRange);
String string = expression.getResult();
if (expression.isWrong == false && !(set.contains(string))) {
set.add(string);
exercisesWriter.println(i + ". " + expression.toString());
answerWriter.println((i + ". " + string));
i++;
}
}
exercisesWriter.close();
answerWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("已经生成题目和答案");
} /**
* 输出结果
*
* @param exercisePath
* 表达式文件路径
* @param answerPath
* 结果文件路径
* @param gradePath
* 输出结果文件路径
*/
public void outputGrade(String exercisePath, String answerPath, String gradePath) { try {
BufferedReader exercisesReader = new BufferedReader(new FileReader(exercisePath));
BufferedReader answerReader = new BufferedReader(new FileReader(answerPath));
PrintWriter gradeWriter = new PrintWriter(new FileWriter(gradePath));
String exercises, answer;
int c = 0, w = 0;
StringBuilder correct = new StringBuilder("Correct: %d (");
StringBuilder wrong = new StringBuilder("Wrong: %d (");
while ((exercises = exercisesReader.readLine()) != null && (answer = answerReader.readLine()) != null) {
int exercisesPoint = exercises.indexOf(".");
int answerPoint = answer.indexOf(".");
if (exercisesPoint != -1 && answerPoint != -1) {
int i = Integer.valueOf(exercises.substring(0, exercisesPoint).trim());
Expression expression = new Expression(exercises.substring(exercisesPoint + 1));
Fraction ans = new Fraction(answer.substring(answerPoint + 1));
if (expression.getResult().equals(ans.toString())) {
c++;
correct.append(" " + i);
if (c % 30 == 0) {
correct.append("\r\n");
}
} else {
w++;
wrong.append(" " + i);
if (w % 30 == 0) {
wrong.append("-r\n");
}
}
}
}
gradeWriter.println(String.format(correct.append(" )").toString(), c));
gradeWriter.println(String.format(wrong.append(" )").toString(), w));
gradeWriter.flush();
exercisesReader.close();
answerReader.close();
gradeWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("已经比较完成,并生成输出文件");
}
}
测试
表达式的输出
随机输出10条20范围以内的表达式和答案
表达式: 结果:
对比上面输出的10条表达式和答案,结果
然后故意修改第2,5,6,7道题的答案,再重新运行一遍,结果如下
随机输出10000条20范围以内的表达式和答案:
项目小结
我觉得这次程序的编写,让我对开发程序有了更深入的了解,体会到沟通与合作的重要性。这次作业的结对队友郑冠华,从讨论需求到编写代码的过程中都帮助了我很多,我觉得我需要提升的地方还有很多,以后还需要继续努力,多加练习。。
四则运算 Java 杨辉鹏,郑冠华的更多相关文章
- java杨辉三角和空心菱形(二维数组篇)
一.杨辉三角 import java.util.Scanner; //导入包 public class Test7 { public static void main(String[]args){ S ...
- Java 杨辉三角的简单实现
package com.lf.trianglenumber; public class Test { public static void main(String[] args) { // 打印的行数 ...
- java杨辉三角
public static void main(String[] args) { Scanner scanner=new Scanner(System.in); System.out.println( ...
- Java的二维数组的应用及杨辉三角的编写
(1) 编写一个程序,生成一个10*10的二维随机整数数组,并将该数组的每行最大值保存于一个一维数组中,将每列平均值保存于另外一个一维数组中并分别输出. (2) 编程输出杨辉三角的前10行. 找出一个 ...
- 使用Java打印杨辉三角
package 杨辉三角; import java.util.Scanner; public class 三角 { private static Scanner scn; public static ...
- Java数组的应用:案例:杨辉三角,三维数组,字符串数组
//import java.util.Arrays; //包含Arrays //import java.util.Random; public class HelloWorld { public st ...
- Java实现杨辉三角
杨辉三角用了两种方法解决 二维数组/递归方法 +—————————————————————————— import java.util.Scanner; public class YangHui02 ...
- [Java练习题] -- 1. 使用java打印杨辉三角
package cn.fzm.demo1.array; import java.util.Scanner; /* * 需求:打印杨辉三角形(行数可以键盘录入) 1 1 1 1 2 1 1 3 3 1 ...
- Java之杨辉三角的实现
今天突然想温习一下Java的基础,想了想就写写杨辉三角吧 1.直接法,利用二维数组 import java.util.Scanner; public class Second { public sta ...
随机推荐
- Jenkins系列之七——前端app自动打包
了两周终于搞掂了,期间各种搜教程.各种懵逼,各种坑对小白来还是很难的额.废话不多说直接开撸~~~ 一.介绍下什么是Gradle Gradle是一个基于JVM的构建工具,是一款通用灵活的构建工具,支持m ...
- Java单元测试(Junit+Mock+代码覆盖率)
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- 《JavaScript总结》apply、call和bind方法
在JavaScript中,apply.call.bind这个三个方法,它们的作用都是为了改变某个函数运行时的上下文, 也就是改变函数体内的this指向. 在一个函数里,存在“定义时上下文”.“运行时上 ...
- 古典音乐 (java基础 继承)
摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 一.前言 小朽不才,最近爱上了听古典音乐收录了,mozart ,贝多芬… ...
- SpringBoot 启动概述
透过现象看本质,SpringApplication 只是将一个典型的Spring应用的启动流程进行了扩展,因此,透彻理解 Spring 容器是打开 Spring Boot 大门的一把钥匙. Sprin ...
- Python机器学习笔记:XgBoost算法
前言 1,Xgboost简介 Xgboost是Boosting算法的其中一种,Boosting算法的思想是将许多弱分类器集成在一起,形成一个强分类器.因为Xgboost是一种提升树模型,所以它是将许多 ...
- TensorFlow.js入门(一)一维向量的学习
TensorFlow的介绍 TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tensor(张量)意味着N维数组,Flow(流)意味着 ...
- .NET里面 abstract class和Interface有什么区别以及用法的展现?
前言 很多新人对这个问题已经看到的厌倦或者是恶心了,有可能是因为比较难理解或者是未理解的情况下对它们的认知不够所以产生的想法是差不多,不用抽奖类和接口我一样能实现我想要的功能. 这句话确实不假,但是实 ...
- nginx支持跨域访问
1,进入nginx的html目录 vim ./crossdomain.xml 具体路径: /usr/local/nginx/html/crossdomain.xml 2,在crossdomain.xm ...
- IEnumerable,ICollection,IList接口问题
最近有一个疑问:IList已经继承了ICollection<T>,而ICollection<T>继承了 IEnumerable<T>, IEnumerable,那为 ...