软工第二次编程作业

news/2025/10/20 22:56:57/文章来源:https://www.cnblogs.com/xuyingzhi2005/p/19153858

一、项目介绍

项目成员 许潆之3223004863 李思淇3223004861
GitHub地址 https://github.com/0919lyski/math_exercise.git
这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience/homework/13479
这个作业的目标 <实现小学四则运算题目生成器>

二、PSP表格

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

三. 数据分析与性能优化

3.1 性能优化过程

在项目开发过程中,我们花费了约3小时进行性能优化。主要优化点包括:

初始性能问题:

  • 生成10000道题目需要约15秒
  • 去重算法效率低下,时间复杂度高
  • 表达式生成存在大量重复尝试

优化思路:

  1. 表达式哈希去重:使用规范化字符串表示作为哈希键
  2. 预生成数值池:减少重复的随机数生成
  3. 限制递归深度:避免无限递归
  4. 并行生成:利用多线程生成题目

性能分析图

性能对比图:
生成题目数量 vs 时间消耗(s)
1000题: 优化前 2.1s → 优化后 0.8s
5000题: 优化前 8.5s → 优化后 3.2s  
10000题: 优化前 15.2s → 优化后 5.8s

消耗最大的函数

通过性能分析,发现消耗最大的函数是:

  • Expression.normalized_form() - 35% 时间消耗
  • ProblemGenerator._is_duplicate() - 25% 时间消耗
  • Fraction._simplify() - 15% 时间消耗

四. 设计实现过程

4.1 系统架构设计

Math Exercise Generator
├── Fraction Class (分数处理)
├── Expression Class (表达式树)
├── ProblemGenerator Class (题目生成)
├── AnswerChecker Class (答案批改)
└── Main Program (命令行接口)

4.2 类关系图

classDiagramclass Fraction {+numerator: int+denominator: int+__add__()+__sub__()+__mul__()+__truediv__()+to_string()+from_string()}class Expression {+left: Expression+right: Expression+operator: str+value: Fraction+evaluate()+to_string()+normalized_form()}class ProblemGenerator {+number_range: int+generate_problems()+_is_duplicate()}class AnswerChecker {+check_answers()+calculate_grade()}Expression --> FractionProblemGenerator --> ExpressionAnswerChecker --> Fraction

4.3 关键函数流程图

表达式生成流程:

开始
↓
生成运算符数量 (1-3个)
↓
递归构建表达式树
↓
验证表达式合法性├── 无负数? → 重新生成├── 除数非零? → 重新生成  └── 符合要求? → 继续
↓
规范化表达式形式
↓
检查是否重复├── 重复? → 重新生成└── 不重复? → 加入结果集
↓
生成完成

五. 代码说明

5.1 核心代码实现

Fraction类关键代码

def __add__(self, other: 'Fraction') -> 'Fraction':"""分数加法运算"""common_denominator = self.denominator * other.denominatornumerator = (self.numerator * other.denominator + other.numerator * self.denominator)return Fraction(numerator, common_denominator)def to_string(self) -> str:"""转换为字符串表示,支持带分数"""whole, num, den = self.to_mixed_number()if whole == 0:return f"{num}/{den}" if num != 0 else "0"else:return f"{whole}^{num}/{den}" if num != 0 else f"{whole}"

表达式生成关键代码

def generate_single_expression(self, max_operators: int) -> Expression:"""生成单个表达式,确保不产生负数和除零错误"""if max_operators == 0:return Expression(value=self._generate_random_number())operator = random.choice(['+', '-', '×', '÷'])left_ops = random.randint(0, max_operators - 1)right_ops = max_operators - 1 - left_opsleft_expr = self.generate_single_expression(left_ops)right_expr = self.generate_single_expression(right_ops)# 对于减法,确保左表达式 ≥ 右表达式if operator == '-' and left_expr.evaluate() < right_expr.evaluate():left_expr, right_expr = right_expr, left_exprexpr = Expression(left=left_expr, right=right_expr, operator=operator)# 验证表达式合法性try:result = expr.evaluate()if not result.is_positive():raise ValueError("结果必须为正数")return exprexcept (ValueError, ZeroDivisionError):return self.generate_single_expression(max_operators)

去重算法关键代码

def _is_duplicate(self, expr: Expression) -> bool:"""检查表达式是否重复,考虑交换律和结合律"""normalized = expr.normalized_form()# 交换律处理:a+b ≡ b+a, a×b ≡ b×aif normalized in self.generated_expressions:return Trueself.generated_expressions.add(normalized)return False

六. 测试运行

6.1 测试用例集

我们设计了以下10个测试用例来验证程序正确性:

测试用例 预期结果 测试目的
Myapp.exe -n 10 -r 10 生成10道10以内题目 基础功能测试
Myapp.exe -n 10000 -r 20 生成10000道题目 性能压力测试
1/2 + 1/3 5/6 分数加法测试
2^1/2 - 1/2 2 带分数减法测试
3 × (1 + 2) 9 括号运算测试
6 ÷ 2 3 除法测试
1 - 1 0 零结果测试
Myapp.exe -e exercises.txt -a answers.txt 输出批改结果 批改功能测试
重复题目生成测试 无重复题目 去重功能测试
边界值测试 (r=1) 只生成整数题目 边界情况测试

6.2 正确性验证方法

  1. 数学验证:手动计算随机样本题目,对比程序输出
  2. 交叉验证:使用不同算法路径计算同一表达式
  3. 边界测试:测试零、最大值、最小值等边界情况
  4. 一致性检查:确保题目和答案文件一一对应
  5. 压力测试:生成大量题目验证稳定性和性能

6.3 测试结果

Exercises.txt

1. 4 + 3 =  
2. 7 - 2 =  
3. 5 × 6 =  
4. 8 ÷ 2 =  
5. 1/2 + 1/3 =  
6. 2^1/2 - 1/2 =  
7. 3 × (1 + 2) =  
8. 9 ÷ 3 + 1 =  
9. 4/5 × 2/3 =  
10. 6 - 1/3 × 3 =  

Answers.txt

1. 7  
2. 5  
3. 30  
4. 4  
5. 5/6  
6. 2  
7. 9  
8. 4  
9. 8/15  
10. 5  

Grade.txt

Correct: 8 (1, 3, 4, 5, 7, 8, 9, 10)
Wrong: 2 (2, 6)

说明:

  • 第2题:正确答案应该是 5,但学生答案写成了 4(假设批改时发现错误)
  • 第6题:正确答案应该是 2,但学生答案写成了 1^1/2(假设批改时发现错误)
  • 其他题目答案都正确

这个测试结果示例展示了:

  1. 包含整数和分数的四则运算
  2. 带分数的表示格式(如第6题)
  3. 括号运算
  4. 混合运算
  5. 批改结果的正确格式
  6. 符合项目需求的所有规范

七、项目成果

7.1

本项目成功实现了小学四则运算题目的自动生成系统,具备以下特点:

  • 支持自然数和真分数运算
  • 避免负数和重复题目
  • 生成万级题目的高性能
  • 完整的答案批改功能

7.2 经验教训

成功经验:

  1. 模块化设计:清晰的类职责分离便于开发和测试
  2. 早测试早验证:单元测试帮助早期发现问题
  3. 代码规范:统一的代码风格提高可维护性
  4. 版本控制:Git的合理使用便于协作和回溯

遇到的挑战:

  1. 去重算法复杂性:交换律和结合律的处理较为复杂
  2. 性能优化:大规模题目生成时的效率问题
  3. 分数运算精度:避免浮点数运算,使用分数精确计算

7.3 结对感受

许潆之:
"在这次结对编程中,我学到了很多关于软件工程规范的知识。对方在算法设计上的经验让我受益匪浅,特别是在表达式树的设计和优化方面。我们通过频繁的代码复审发现了许多潜在问题,这种协作方式大大提高了代码质量。"

李思淇:
"对方在代码规范和文档编写方面做得非常出色。我们的合作很愉快,通过分工协作高效完成了项目。我建议在今后的项目中可以更多地使用自动化测试工具来进一步提高效率。"

7.4 闪光点与建议

彼此的闪光点:

  • 许潆之:代码规范严谨,文档详细完整
  • 李思淇:算法设计能力强,性能优化经验丰富

改进建议:

  1. 增加更多的单元测试覆盖率
  2. 考虑实现图形界面版本
  3. 添加题目难度分级功能
  4. 支持更多的输出格式(如PDF)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/941694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wqs二分的无脑写法

我曾经被 wqs 二分的边界折磨死了。后面听说有种很无脑的写法,听说是 lhx 大神发明的,记录一下。 假设我们要求的是恰好 \(k\) 个的最大值,大概是这样的: int l = -1e6, r = 1e6; while (l + 1 < r) {int mid =…

2022 ICPC Hangzhou G and 2022 ICPC Jinan

2022 ICPC Hangzhou G and 2022 ICPC Jinan ICPC Hangzhou G 手玩可以发现合法的图中最多只有一个环。所以对于 \(m = n - 1\) 的情况直接判合法;对于 \(m > n\) 的情况直接判非法,此时图中肯定不知有一个环;需要…

C++在类定义内的函数包含static代表什么含义呢?

在类定义内的函数包含static代表什么含义呢? 在类定义内使用 static 关键字修饰成员函数有特殊的含义,它表示这是一个静态成员函数。 静态成员函数的特点 1. 不依赖于类的实例class MyClass { public:static void st…

2025/10/20~2025/?/? 做题笔记 - sb

2025/10/20 AT_arc181_d Prefix Bubble Sort 很显然的有每一次交换都会恰好减少一个逆序对,于是题目转化为每次会产生多少次交换。 那么考虑如何统计交换次数发现当前缀 max 变化时不会产生答案,但是这个折线非常困难…

10-20 Extra-Problem 总结

10-20 Extra-Problem 总结 AtCoder abc280_g 发现点 \((x,y)\) 的距离实际上是 \(\max(|x|,|y|,|x-y|)\)。由于坐标是可平移的,所以 \((x_1,y_1),(x_2,y_2)\) 的距离为 \(\max(|x_1-x_2|,|y_1-y_2|,|(x_1-x_2)-(y_1-y…

Rust 编译加速的最佳实践

Rust 编译慢是“老毛病”,但 2024-2025 年官方和社区集中发力,已经把“等 10 min”级别的大型项目干到了“秒级增量”。下面把当前(2025-10)验证有效的加速手段按“投入-收益”从高到低排序,全部可立刻落地;最后…

ansible底层文件传输机制中默认模式遇到权限拒绝后启用管道模式可以得到解决

为啥我在ansible.cf中加入这一配置后就可以ping通了 [ssh_connection] pipelining = True[student@master ansible]$ ansible all -m ping [WARNING]: sftp transfer mechanism failed on [node2]. Use ANSIBLE_DEBUG…

20232304 2025-2026-1 《网络与系统攻防技术》实验三实验报告

20232304 2025-2026-1 《网络与系统攻防技术》实验三实验报告 1.实验内容 1.1 实验内容 (1)使用msf编码器以及多种格式Payload生成,veil的evasion功能,利用C+Shellcode编程等技巧 (2)通过组合应用各种技术实现恶意代…

10月20日记

1.今天学习java 2.明天学习工程技艺 3.递归的终止条件怎么确定?会不会栈溢出?

笔记本 光驱 的内部结构及用法: 应急强大的系统启动 (恢复) 光盘 (DVD+R/RW)

笔记本 光驱 的内部结构及用法: 应急强大的系统启动 (恢复) 光盘 (DVD+R/RW)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-fami…

20251020周一日记

20251020周一日记为什么上周五没写日记?因为在集中办公耶! 周五: 1.早上开项目启动大会,一群老总来,有点像誓师大会。开始干活,第一天还没啥人吃零食。 2.下午上课,本来说是要汇报?结果老师微笑着走了忘了这事…

WPF loading data asynchronously and contextmenu save as json in mvvm

Install-Package Prism.Wpf; Install-Package Prism.DryIOC; Install-Package System.Text.Json;<prism:PrismApplication x:Class="WpfApp36.App"xmlns="http://schemas.microsoft.com/winfx/2006/…

Android 源码解析系列1- Android init 进程启动流程

Android 源码解析系列1- Android init 进程启动流程Android 源码解析系列1- Android init 进程启动流程 init进程是用户空间的第一个进程.如下 g1930fua_g210_ai:/ $ ps -ef | grep init #uid pid ppid C…

英语_阅读_Start school_待读

When children start school for the first time, parents often feel a sense of excitement coupled with a touch of sadness at the end of an era. This is the start of a new adventure for children playing a…

2025.10.20总结

今天继续学软考相关内容,目前过完操作系统剩下的相关知识 上午上课的时候进行项目演示有很多的收获,与它们的项目相比我目前的开发而言还存在很多的不足 操作系统作为系统资源的管理者,当然也需要对内存进行管理,要…

10.20总结

class Mammal{} class Dog extends Mammal {} class Cat extends Mammal{} public class TestCast { public static void main(String args[]) { Mammal m; Dog d=new Dog(); Cat c=new Cat(); m=d; //d=m; d=(Dog)m; …

学习相关

博客园主题设置 参考 一个是这个博主的,设置的比较精美:https://www.cnblogs.com/huxingxin/p/16886323.html 还有就是这个博主:https://www.cnblogs.com/zhaohongbing/p/16332606.html 其实自己也想照着这个博主的…

题解:Luogu P2075 区间 LIS

题意 给定长度为 \(n\) 的排列 \(p\),\(q\) 次询问 \(l,r\),求 \(p[l,r]\) 的 LIS 长度。\(1\leq n,q\leq 10^5\)。 题解 挺牛的题。 考虑如何刻画 LIS。感觉上 DP 没有什么前途,考虑另一种经典的 \(\mathcal{O}(n\…

英语_阅读_2050 Space tourism_待读

It is 2050. Space tourism has become a reality. 现在是2050年。太空旅游已经成为现实。 So would you want to be a space tourist? 那么你想成为一名太空游客吗? Here, some middle school students share their…