作业三:结对项目

这个作业属于哪个课程计科2班
这个作业要求在哪里 作业要求
这个作业的目标 < 要求实现一个自动生成小学四则运算题目的命令行程序 >

[作业地址] (https://www.cnblogs.com/aaaaaa1111/)

href="https://github.com/cr1017/3122004813" target="_blank" rel="noopener nofollow">https://www.cnblogs.com/aaaaaa1111/)

 

 1. PSP2.1表格

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

60

120

· Estimate

· 估计这个任务需要多少时间

30

60

Development

开发

100

220

· Analysis

· 需求分析 (包括学习新技术)

100

180

· Design Spec

· 生成设计文档

60

100

· Design Review

· 设计复审 (和同事审核设计文档)

30

30

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

30

30

· Design

· 具体设计

120

150

· Coding

· 具体编码

600

1500

· Code Review

· 代码复审

50

60

· Test

· 测试(自我测试,修改代码,提交修改)

150

60

Reporting

报告

80

80

· Test Report

· 测试报告

30

40

· Size Measurement

· 计算工作量

20

10

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

40

20

合计

 

1150

2400

二·设计实现

1.表达式生成:根据输入的两个参数决定表达式的数量及数值范围,随机生成数值范围内的自然数及运算符,随机插入左括号并在相应的位置插入右括号。

2.分数:专门写了一个类Fraction来生成分数,并且有约分的功能。

3.负数:负数只会在减法运算时产生,每当遇到减法运算时,若运算结果出现负数,就重新生成新的表达式。

4.计算:将整数也当成分数进行计算,先将上面生成的表达式(以字符串存储)分别入数字栈和符号栈,再根据符号优先级计算最终结果。

 

三.代码

分数类

点击查看代码
public class Fraction {
int x;//分子
int y;//分母
private Fraction temp;
public Fraction(int a, int b) {
x = a;
y = b;
}
Fraction add(Fraction r) {
temp = new Fraction(0, 0);
temp.x = x * r.y + y * r.x;
temp.y = y * r.y;
return temp;
}
Fraction minus(Fraction r) {
temp = new Fraction(0, 0);
temp.x = x * r.y - y * r.x;
temp.y = y * r.y;
return temp;
}
Fraction multiply(Fraction r) {
temp = new Fraction(0, 0);
temp.x = x * r.x;
temp.y = y * r.y;
return temp;
}
Fraction divide(Fraction r) {
temp = new Fraction(0, 0);
temp.x = x * r.y;
temp.y = y * r.x;
return temp;
}
String print() {
/**
* 计算结果化简
*/
if (x == 0) {
return "0";
} else {
int n;
if (x > y)
n = x;
else
n = y;
int maxn = 0;
for (int i = 1; i <= n; ++i) { //约分
if (x % i == 0 && y % i == 0)
maxn = i;
}
int a = x / maxn;
int b = y / maxn;
if (a == b)
return "1";
else if(b==1)
return a+"";
else
return a + "/" + b;
}
}
}

表达式生成

点击查看代码
public class CreateExercise {
String[] sign = {"+", "-", "x", "÷", "/"};
int range_num;
Random random = new Random();
public void setRange_num(int range_num) {
this.range_num =range_num;
}
public String create() {
String str = "";
int local = random.nextInt(3);
for (int j = 0; j < 3; j++) {
if (local == 0 && j == 0) {
str += "(";
} else if (local == 2 && j == 1) {
str += "(";
}
str += random.nextInt(range_num) % range_num + 1; //产生指定范围随机数
if (local == 0 && j == 1) {
str += ")";
}
if (local == 2 && j == 2) {
str += ")";
}
String signElement = sign[random.nextInt(5)];//产生随机运算符号
str += signElement;
if (signElement == "/") {
str += random.nextInt(range_num) % range_num + 1;
signElement = sign[random.nextInt(5)];
while (true) {
if (signElement != "/") {
str += signElement;
break;
}
signElement = sign[random.nextInt(5)];
}
}
}
str = str.substring(0, str.length() - 1);
return str;
}
public void belongFraction(String strfraction) {
/**

* 处理分数计算

*/
String[] fractionlist = null;
if (strfraction.contains("+")) {
fractionlist = strfraction.split("\\+");
CalculateFraction(fractionlist, 0);
} else if (strfraction.contains("-")) {
fractionlist = strfraction.split("-");
CalculateFraction(fractionlist, 1);
} else if (strfraction.contains("x")) {
fractionlist = strfraction.split("\\x");
CalculateFraction(fractionlist, 2);
} else if (strfraction.contains("÷")) {
fractionlist = strfraction.split("÷");
CalculateFraction(fractionlist, 3);
}
}
public void CalculateFraction(String[] strlist, int flag) {
/**

* 分数的四种基本运算

*/
String[] fraction1 = new String[2];
String[] fraction2 = new String[2];
if (strlist[0].contains("/"))
fraction1 = strlist[0].split("/");
else {
fraction1[0] = strlist[0];
fraction1[1] = "1";
}
if (strlist[1].contains("/"))
fraction2 = strlist[1].split("/");
else {
fraction2[0] = strlist[1];
fraction2[1] = "1";
}
Fraction fr1 = new Fraction(Integer.parseInt(fraction1[0]), Integer.parseInt(fraction1[1]));
Fraction fr2 = new Fraction(Int

计算

点击查看代码
public class Calculator {

/**

* 数字栈:存储表达式中的数字

*/

private Stack numStack = null;

/**

* 符号栈:存储表达式中的运算符和括号

*/

private Stack charStack = null;

/**

* 计算四则运算表达式,返回计算结果

*

*/

public String calculate(String numStr) {

numStr = removeStrSpace(numStr);

if (numStr.length() > 1 && !"=".equals(numStr.charAt(numStr.length() - 1) + "")) {

numStr += "=";

}

if (!isStandard(numStr)) {

return "0";

}

numStack = new Stack();

charStack = new Stack();

StringBuffer temp = new StringBuffer();

for (int i = 0; i < numStr.length(); i++) {

char ch = numStr.charAt(i);

if (isNumber(ch) || ch == '/') {

temp.append(ch);

} else {

String tempStr = temp.toString();

if (!tempStr.isEmpty()) {

numStack.push(tempStr);

temp = new StringBuffer();

}

while (!comparePri(ch) && !charStack.empty()) {

String a = numStack.pop();

String b = numStack.pop();

Fraction f1 = null;

Fraction f2 = null;

if (a.contains("/")) {

String[] alist = a.split("/");

f1 = new Fraction(Integer.parseInt(alist[0]), Integer.parseInt(alist[1]));

} else {

f1 = new Fraction(Integer.parseInt(a), 1);

}

if (b.contains("/")) {

String[] blist = b.split("/");

f2 = new Fraction(Integer.parseInt(blist[0]), Integer.parseInt(blist[1]));

} else {

f2 = new Fraction(Integer.parseInt(b), 1);

}

switch (charStack.pop()) {

case '+':

numStack.push(f2.add(f1).print());

break;

case '-':

if ((f1.x/f1.y) >= (f2.x/f2.y)) {

return null;

}

numStack.push(f2.minus(f1).print());

break;

case 'x':

numStack.push(f2.multiply(f1).print());

break;

case '÷':

if (f1.x==0){

return null;

}

numStack.push(f2.divide(f1).print());

break;

default:

break;

}

}

if (ch != '=') {

charStack.push(new Character(ch));

if (ch == ')') {

charStack.pop();

charStack.pop();

}

}

}

}

return numStack.pop();

}

private String removeStrSpace(String str) {

return str != null ? str.replaceAll(" ", "") : "";

}

private boolean isStandard(String numStr) {

if (numStr == null || numStr.isEmpty())

return false;

Stack stack = new Stack();

boolean b = false;

for (int i = 0; i < numStr.length(); i++) {

char n = numStr.charAt(i);

if (!(isNumber(n) || "(".equals(n + "") || ")".equals(n + "")

|| "+".equals(n + "") || "-".equals(n + "")

|| "x".equals(n + "") || "÷".equals(n + "") || "/".equals(n + "")

|| "=".equals(n + ""))) {

return false;

}

if ("(".equals(n + "")) {

stack.push(n);

}

if (")".equals(n + "")) {

if (stack.isEmpty() || !"(".equals((char) stack.pop() + ""))

return false;

}

if ("=".equals(n + "")) {

if (b)

return false;

b = true;

}

}

if (!stack.isEmpty())

return false;

if (!("=".equals(numStr.charAt(numStr.length() - 1) + "")))

return false;

return true;

}

private boolean isNumber(char num) {

if (num >= '0' && num <= '9')

return true;

return false;

}

/**

* 比较优先级:如果当前运算符比栈顶元素运算符优先级高则返回true,否则返回false

*/

private boolean comparePri(char symbol) {

if (charStack.empty()) {

return true;

}

char top = charStack.peek();

if (top == '(') {

return true;

}

switch (symbol) {

case '(':

return true;

case 'x': {

if (top == '+' || top == '-')

return true;

else

return false;

}

case '÷': {

if (top == '+' || top == '-')

return true;

else

return false;

}

case '+':

return false;

case '-':

return false;

case ')':

return false;

case '=':

return false;

default:

break;

}

return true;

}

String getFinalResult(String str) {

if (!str.contains("/"))

return str;

String[] part = str.split("/");

int a = Integer.parseInt(part[0]);

int b = Integer.parseInt(part[1]);

if (a == b)

return "1";

else if (a > b && a % b != 0) {

return a / b + "’" + a % b + "/" + b;

} else if (a < b && -a > b && (-a) % b != 0) {

return "-" + (-a) / b + "’" + (-a) % b + "/" + b;

} else if (b == 1)

return a + "";

else

return a + "/" + b;

}

}

生成txt文本

点击查看代码
public class IO {

File ExerciseFile = null;

File AnswerFile = null;

String filename = "";

BufferedWriter ExerciseOut = null;

BufferedWriter AnswerOut = null;

public IO() {

if (this.CreateFile()) {

this.setOutBufferedWriter();

} else

System.out.println("创建文件失败!");

}

public void setOutBufferedWriter() {

try {

this.ExerciseOut = new BufferedWriter(new FileWriter(ExerciseFile));

this.AnswerOut=new BufferedWriter(new FileWriter(AnswerFile));

} catch (IOException e) {

e.printStackTrace();

}

}

public boolean CreateFile() {

String relativelyPath=System.getProperty("user.dir");

ExerciseFile = new File(relativelyPath+"\\Exercise" + ".txt");

AnswerFile = new File(relativelyPath+"\\Answer" + ".txt");

if (ExerciseFile.exists()) {

ExerciseFile.delete();

}

if (AnswerFile.exists()) {

AnswerFile.delete();

}

try {

ExerciseFile.createNewFile();

AnswerFile.createNewFile();

} catch (IOException e) {

e.printStackTrace();

}

return true;

}

public boolean WriteToFile(String content, int flag) {

try {

switch (flag) {

case 0:

ExerciseOut.write(content);

ExerciseOut.write("\r\n");

ExerciseOut.flush();

return true;

case 1:

AnswerOut.write(content);

AnswerOut.write("\r\n");

AnswerOut.flush();

return true;

}

} catch (IOException e) {

e.printStackTrace();

}

return false;

}

public boolean CloseOutBufferedWriter() {

try {

ExerciseOut.close();

AnswerOut.close();

return true;

} catch (IOException e) {

e.printStackTrace();

}

return false;

}

}

主函数启动类

点击查看代码
public class MyApp {

public static void main(String[] args) {

Scanner scan = new Scanner(System.in);

System.out.print("请输入希望生成的题目数量:");

int problems_num = scan.nextInt();

System.out.print("请输入题目的数值范围n(范围为0到n):");

int range_num = scan.nextInt();

System.out.print("是否开始答题(yes/no):");

String is_doNow=scan.next();

LinkedHashMap rightAnswerMap = new LinkedHashMap();

LinkedHashMap exerciseMap = new LinkedHashMap();

ArrayList rightRecord = new ArrayList();

ArrayList wrongRecord = new ArrayList();

CreateExercise ce = new CreateExercise();

IO save = new IO();

ce.setRange_num(range_num);

for (int i = 1; i <= problems_num; i++) {

String problem = ce.create();

exerciseMap.put(i,problem);

String ns = problem;

int rightbrackets;

int leftbrackets;

if (problem.contains(")")) {

rightbrackets = problem.indexOf(")");

leftbrackets = problem.indexOf("(");

if (rightbrackets != problem.length() - 1 && problem.charAt(rightbrackets + 1) == '/') {

StringBuilder sb = new StringBuilder(problem);

if (leftbrackets - 1 > 0 && problem.charAt(leftbrackets - 1) == '÷')

sb.replace(rightbrackets + 1, rightbrackets + 2, "x");

else

sb.replace(rightbrackets + 1, rightbrackets + 2, "÷");

ns = sb.toString();

}

}

Calculator cal = new Calculator();

String result = cal.calculate(ns);

if (result != null) {

result = cal.getFinalResult(result);

System.out.println(i + ": " + problem + "=" );

rightAnswerMap.put(i, result);

if (!save.WriteToFile(i + ": " + problem + "=", 0)) {

System.out.println("生成Exercise文件失败!");

System.exit(0);

}

if (!save.WriteToFile(+ i + ": " + problem + "=" + result, 1)) {

System.out.println("生成Answer文件失败!");

System.exit(0);

}

} else {

i--;

}

}

if(is_doNow.equals("yes")){

System.out.println("请输入答案(带分数用“ ’ ”分隔,如1’1/2):");

for (int i = 1; i <= problems_num; i++) {

System.out.print( + i + ": " + exerciseMap.get(i) + "=");

String input = scan.next();

if (rightAnswerMap.get(i).equals(input))

rightRecord.add(i);

else

wrongRecord.add(i);

}

System.out.println("结果为:");

if (rightRecord.size()!=0){

System.out.print("正确题目:"+rightRecord.size()+" (");

for (int i=0;i

System.out.print(rightRecord.get(i)+",");

System.out.println(rightRecord.get(rightRecord.size()-1)+")");

}

else

System.out.println("正确题目:"+rightRecord.size());

if (wrongRecord.size()!=0){

System.out.print("错误题目:"+wrongRecord.size()+" (");

for (int i=0;i

System.out.print(wrongRecord.get(i)+",");

System.out.println(wrongRecord.get(wrongRecord.size()-1)+")");

}

else

System.out.println("错误题目:"+wrongRecord.size());

}

if (save.CloseOutBufferedWriter())

System.out.println("题目和答案文本创建成功");

else

System.out.println("题目和答案文本创建失败");

}

}

四.测试运行
生成10000道题目
image
部分题目及答案
image

五.答案统计
image

故意答错 1,3题
image

代码覆盖率
image

posted @   弗兰契斯科  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示