结对项目
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/ |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230 |
这个作业的目标 | 编程开发结对项目,实现项目单元测试 |
成员一 | 3122004755杨睿 |
成员二 | 3122004960木萨江·米吉提 |
github链接
https://github.com/rayrain13/pair-project
psp表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 40 |
Estimate | 估计这个任务需要多少时间 | 20 | 15 |
Development | 开发 | 360 | 400 |
Analysis | 需求分析 (包括学习新技术) | 80 | 60 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 20 |
Design | 具体设计 | 60 | 70 |
Coding | 具体编码 | 90 | 110 |
Code Review | 代码复审 | 30 | 15 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 45 |
Reporting | 报告 | 60 | 50 |
Test Repor | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 30 |
合计 | 1020 | 955 |
性能分析
通过效能分析得,占用时间最长的是generateProblems方法,主要用于生成指定数量的数学问题,并且确保不重复。
流程图
接口设计和实现
主类ArithmeticProblemGenerator,测试类ArithmeticProblemGeneratorTest
主类中包括:
主方法main:接受命令行参数,以决定生成问题或批改练习。解析输入参数,调用相应的方法。
Fraction类:表示分数,包含分子和分母。提供加、减、乘、除等运算方法,确保分数简化为最简形式。包含与其他分数比较大小的方法以及格式化为字符串的方法。
Expression类:表示一个算术表达式,包括一个Fraction值和其字符串表示。
generateProblems:生成指定数量的独特问题,并将其写入文件。
代码说明
Fraction分数类:用于表示分数并进行基本的四则运算。
Fraction 类:
包含两个属性:numerator(分子)和 denominator(分母)。
构造函数:
接受分子和分母作为参数。
检查分母是否为零,如果为零则抛出异常。
通过调用 gcd 方法计算分子和分母的最大公约数,以简化分数。
如果分母为负,则将分子和分母同时取反,以保持分数的标准形式(分母为正)。
static class Fraction {
int numerator;
int denominator;
public Fraction(int numerator, int denominator) {
if (denominator == 0) {
throw new IllegalArgumentException("Denominator cannot be zero");
}
int gcd = gcd(Math.abs(numerator), Math.abs(denominator));
this.numerator = numerator / gcd;
this.denominator = denominator / gcd;
if (this.denominator < 0) {
this.numerator = -this.numerator;
this.denominator = -this.denominator;
}
}
private static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
public Fraction add(Fraction other) {
int newNumerator = this.numerator * other.denominator + other.numerator * this.denominator;
int newDenominator = this.denominator * other.denominator;
return new Fraction(newNumerator, newDenominator);
}
public Fraction subtract(Fraction other) {
int newNumerator = this.numerator * other.denominator - other.numerator * this.denominator;
int newDenominator = this.denominator * other.denominator;
return new Fraction(newNumerator, newDenominator);
}
public Fraction multiply(Fraction other) {
return new Fraction(this.numerator * other.numerator, this.denominator * other.denominator);
}
public Fraction divide(Fraction other) {
if (other.numerator == 0) {
throw new ArithmeticException("Cannot divide by zero");
}
return new Fraction(this.numerator * other.denominator, this.denominator * other.numerator);
}
generateProblems 方法用于生成指定数量的数学问题并确保它们的唯一性。
初始化:
创建一个 Set
创建两个 List
循环生成问题:
使用 while 循环,直到生成的问题数量达到 count。
调用 generateExpression(range, MAX_OPERATORS) 方法生成一个随机表达式(expr)。
构建问题字符串 problem,格式为 expr.repr + " = "。
确保唯一性:
检查 uniqueProblems 中是否已包含该问题。
如果未包含,则将问题添加到 uniqueProblems、problems 和答案列表 answers 中。
写入文件:
调用 writeToFile("Exercises.txt", problems) 将生成的问题写入文件。
调用 writeToFile("Answers.txt", answers) 将对应的答案写入文件。
static void generateProblems(int count, int range) {
Set<String> uniqueProblems = new HashSet<>();
List<String> problems = new ArrayList<>();
List<String> answers = new ArrayList<>();
while (problems.size() < count) {
Expression expr = generateExpression(range, MAX_OPERATORS);
String problem = expr.repr + " = ";
if (!uniqueProblems.contains(problem)) {
uniqueProblems.add(problem);
problems.add(problem);
answers.add(expr.value.toString());
}
}
writeToFile("Exercises.txt", problems);
writeToFile("Answers.txt", answers);
}
单元测试
测试函数:
import org.junit.Test;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.*;
public class ArithmeticProblemGeneratorTest {
@Test
public void testFractionAddition() {
ArithmeticProblemGenerator.Fraction f1 = new ArithmeticProblemGenerator.Fraction(1, 2);
ArithmeticProblemGenerator.Fraction f2 = new ArithmeticProblemGenerator.Fraction(1, 3);
ArithmeticProblemGenerator.Fraction result = f1.add(f2);
assertEquals("5/6", result.toString());
}
@Test
public void testFractionSubtraction() {
ArithmeticProblemGenerator.Fraction f1 = new ArithmeticProblemGenerator.Fraction(1, 2);
ArithmeticProblemGenerator.Fraction f2 = new ArithmeticProblemGenerator.Fraction(1, 3);
ArithmeticProblemGenerator.Fraction result = f1.subtract(f2);
assertEquals("1/6", result.toString());
}
@Test
public void testFractionMultiplication() {
ArithmeticProblemGenerator.Fraction f1 = new ArithmeticProblemGenerator.Fraction(1, 2);
ArithmeticProblemGenerator.Fraction f2 = new ArithmeticProblemGenerator.Fraction(2, 3);
ArithmeticProblemGenerator.Fraction result = f1.multiply(f2);
assertEquals("1/3", result.toString());
}
@Test
public void testFractionDivision() {
ArithmeticProblemGenerator.Fraction f1 = new ArithmeticProblemGenerator.Fraction(1, 2);
ArithmeticProblemGenerator.Fraction f2 = new ArithmeticProblemGenerator.Fraction(2, 3);
ArithmeticProblemGenerator.Fraction result = f1.divide(f2);
assertEquals("3/4", result.toString());
}
@Test
public void testGenerateExpression() {
ArithmeticProblemGenerator.Expression expr = ArithmeticProblemGenerator.generateExpression(10, 2);
assertNotNull(expr);
assertNotNull(expr.value);
assertFalse(expr.repr.isEmpty());
}
@Test
public void testGenerateProblems() {
ArithmeticProblemGenerator.generateProblems(5, 10);
List<String> exercises = ArithmeticProblemGenerator.readFile("Exercises.txt");
List<String> answers = ArithmeticProblemGenerator.readFile("Answers.txt");
assertEquals(5, exercises.size());
assertEquals(5, answers.size());
}
@Test
public void testEvaluateExpression() {
String expression = "(1/2 + 1/3)";
ArithmeticProblemGenerator.Fraction result = ArithmeticProblemGenerator.evaluateExpression(expression);
assertEquals("5/6", result.toString());
}
}
测试结果:
Excercises.txt
Answers.txt
覆盖率:
项目小结
木萨江:我们充分发挥了各自的优势取长补短,提高了项目完成的质量。但是在项目初期,由于沟通不畅,我们浪费了一些时间在重复的工作上。在项目执行过程中,我们要合理安排时间,确保各项工作按时完成。总之,本次结对项目使我们受益匪浅。我们相信,在今后的工作中,我们会更好地运用本次项目的经验,不断提高自己的能力,实现共同成长。
杨睿:在此次结对项目中,我们通过密切合作完成了项目任务,提升了问题分析和解决能力。结对编程促进了双方的沟通与协调,减少了错误的发生,同时相互学习对方的长处,共同提高了代码质量和开发效率。这次合作为今后的项目开发奠定了良好的基础。