软件工程第三次作业:四则运算题目生成器 - Nyanya-

news/2025/10/21 20:16:19/文章来源:https://www.cnblogs.com/Nyanya--/p/19156343

四则运算题目生成器 - 结对项目报告

项目信息 详情
课程 软件工程
作业要求 结对项目
项目目标 实现一个四则运算题目生成器,支持有理数运算,规范软件开发流程,熟悉结对编程
结对成员 姓名1: [杨浩] 学号1: [3123004462] 姓名2: [刘霆浩] 学号2: [3123004451]
GitHub仓库 ymxc152/four_fundamental_rules

1. PSP表格

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

2. 项目概述

2.1 项目简介

本项目是一个基于Python开发的小学四则运算题目生成器,采用模块化设计,支持命令行使用方式。系统能够生成符合小学教学要求的四则运算题目,支持自然数、真分数、带分数的混合运算。

2.2 技术特点

  • 有理数运算:支持自然数、真分数、带分数的完整运算体系
  • 表达式解析:实现完整的四则运算表达式解析和求值
  • 智能去重:基于交换律和结合律的题目去重算法
  • 规则验证:确保题目符合小学数学教学要求(无负数结果、分数除法结果为真分数等)
  • 模块化架构:清晰的模块划分,便于测试和维护
  • 完善的异常处理:处理各种边界情况和异常情况
  • 自动化测试:单元测试、集成测试的完整测试体系

2.3 作业规范实现

  • 输入输出规范:严格按照命令行参数传递,支持-n、-r、-e、-a参数
  • 文件格式规范:输出Exercises.txt、Answers.txt、Grade.txt文件
  • 题目规则:最多3个运算符,支持括号,无重复题目
  • 分数格式:真分数格式如3/5,带分数格式如2'3/8
  • 性能要求:支持生成最多10000道题目

3. 模块接口与设计

3.1 整体架构设计

本项目采用模块化设计,将四则运算题目生成器分解为多个独立且功能明确的模块,便于维护、测试和扩展。

四则运算题目生成器
├── main.py                    # 主入口程序
├── src/                       # 核心算法模块
│   ├── rational.py           # 有理数类型及运算模块
│   ├── expression_parser.py  # 表达式解析模块
│   ├── problem_generator.py  # 题目生成模块
│   ├── deduplicator.py       # 去重算法模块
│   └── file_utils.py         # 文件处理工具模块
├── tests/                     # 测试模块
│   ├── test_rational.py      # 有理数测试
│   ├── test_parser.py        # 解析器测试
│   ├── test_generator.py     # 生成器测试
│   └── test_main.py          # 主程序测试
├── student_answers/           # 学生答案目录(测试用)
├── Exercises.txt             # 生成的题目文件
├── Answers.txt               # 生成的答案文件
└── requirements.txt          # 项目依赖

3.2 核心算法流程图

3.2.1 主程序流程图

flowchart TDA[程序启动] --> B[解析命令行参数]B --> C{参数类型?}C -->|生成模式| D[检查-n和-r参数]C -->|批改模式| E[检查-e和-a参数]D --> F{参数有效?}E --> G{文件/目录存在?}F -->|否| H[显示使用说明并退出]F -->|是| I[生成题目]G -->|否| J[显示错误信息并退出]G -->|是| K{答案路径类型?}K -->|单个文件| L[批改单个学生]K -->|目录| M[批改多个学生]I --> N[写入Exercises.txt和Answers.txt]L --> O[生成单个Grade.txt]M --> P[为每个学生生成Grade.txt]N --> Q[显示成功信息]O --> R[显示批改结果]P --> S[显示总体批改结果]Q --> T[程序结束]R --> TS --> T

3.2.2 题目生成流程

flowchart TDA[开始生成题目] --> B[初始化题目集合]B --> C[生成随机表达式]C --> D[解析表达式]D --> E[计算表达式值]E --> F{结果符合规则?}F -->|否| CF -->|是| G[检查是否重复]G --> H{题目重复?}H -->|是| CH -->|否| I[添加到题目集合]I --> J{达到题目数量?}J -->|否| CJ -->|是| K[格式化输出]K --> L[结束生成]

3.2.3 有理数运算流程

flowchart TDA[有理数输入] --> B{类型判断}B -->|自然数| C[直接运算]B -->|真分数| D[分数运算]B -->|带分数| E[转换为假分数]E --> DD --> F[约分处理]F --> G[结果格式化]C --> GG --> H[输出结果]

3.3 核心模块接口说明

3.3.1 有理数类型模块 (src/rational.py)

主类接口:

class Rational:"""有理数类,支持自然数、真分数、带分数的运算Attributes:numerator (int): 分子denominator (int): 分母Methods:__init__(numerator, denominator=1): 构造函数__add__(other): 加法运算__sub__(other): 减法运算__mul__(other): 乘法运算__truediv__(other): 除法运算__eq__(other): 相等比较__lt__(other): 小于比较__le__(other): 小于等于比较__gt__(other): 大于比较__ge__(other): 大于等于比较__neg__(): 取负运算__abs__(): 取绝对值to_string(): 转换为字符串格式from_string(s): 从字符串创建有理数simplify(): 约分处理gcd(a, b): 计算最大公约数"""

功能特点:

  • 支持自然数、真分数、带分数的统一表示
  • 自动约分和格式化,正确处理负数带分数
  • 重载运算符,支持直观的数学运算
  • 处理除零异常和负数情况
  • 支持字符串解析和格式化

3.3.2 表达式解析模块 (src/expression_parser.py)

核心类接口:

class ExpressionParser:"""表达式解析器,支持四则运算和括号优先级Methods:parse(expression): 解析表达式并返回结果tokenize(expression): 将表达式分解为标记列表infix_to_postfix(tokens): 中缀表达式转后缀表达式evaluate_postfix(postfix_tokens): 计算后缀表达式apply_operator(left, operator, right): 应用运算符"""class Token:"""表达式标记类Attributes:type (str): 标记类型 ('NUMBER', 'OPERATOR', 'PARENTHESIS')value (str): 标记值"""

功能特点:

  • 支持四则运算和括号优先级
  • 使用中缀转后缀算法处理运算符优先级
  • 支持有理数运算和分数解析
  • 完善的错误处理和异常捕获
  • 支持负数、分数、带分数的表达式解析

3.3.3 题目生成模块 (src/problem_generator.py)

核心类接口:

class ProblemGenerator:"""题目生成器,生成符合规则的四则运算题目Methods:generate_problems(count, max_value): 生成指定数量的题目generate_single_problem(max_value): 生成单个题目create_expression(max_value): 创建随机表达式"""class ProblemValidator:"""题目验证器,验证题目是否符合规则Methods:validate_problem(expression, answer): 验证题目是否符合规则is_valid_result(result): 检查结果是否有效"""class DeduplicationStats:"""去重统计类,记录去重统计信息Attributes:total_generated: 总生成题目数duplicates_found: 发现重复数final_count: 最终题目数"""

功能特点:

  • 随机生成符合规则的表达式
  • 控制运算符数量(最多3个)
  • 确保无负数中间结果和最终结果
  • 支持分数运算规则,避免分数除法
  • 智能去重,避免重复题目

3.3.4 去重算法模块 (src/deduplicator.py)

核心类接口:

class Deduplicator:"""题目去重器根据需求6,任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如:- 23 + 45 和 45 + 23 是重复的(交换律)- 6 × 8 和 8 × 6 是重复的(交换律)- 3+(2+1) 和 1+2+3 是重复的(通过交换可以变换)- 1+2+3 和 3+2+1 不是重复的(树结构不同)Methods:canonicalize_expression(expression): 将表达式转换为规范形式is_duplicate(expression): 检查表达式是否重复deduplicate_problems(problems): 对题目列表进行去重reset(): 重置去重器状态get_statistics(): 获取去重统计信息"""

去重策略:规范化去重

  • 表达式规范化:将表达式转换为规范形式进行比较
  • 交换律支持:对+和×运算符应用交换律(a+b = b+a, a×b = b×a)
  • 树结构保持:保持左结合性,不同结构不视为重复
  • 高效查找:使用集合存储规范化形式,O(1)时间复杂度

核心算法:

  1. 构建表达式树:将中缀表达式转换为二叉树结构
  2. 规范化处理:对交换律运算符的操作数按字典序排序
  3. 树转字符串:将规范化的树转换为标准字符串表示
  4. 重复检测:使用集合快速检查规范化形式是否已存在

3.3.5 文件处理工具模块 (src/file_utils.py)

核心类接口:

class FileHandler:"""文件处理器,负责题目和答案文件的读写Methods:write_exercises(problems, filename): 写入题目文件write_answers(problems, filename): 写入答案文件read_exercises(filename): 读取题目文件read_answers(filename): 读取答案文件write_grade_results(results, filename): 写入批改结果grade_exercises(exercises, answers): 批改题目find_answer_files(directory): 查找答案文件"""class FileValidator:"""文件验证器,验证文件格式和内容Methods:validate_exercise_file(filename): 验证题目文件validate_answer_file(filename): 验证答案文件is_valid_exercise_format(line): 检查题目格式is_valid_answer_format(line): 检查答案格式"""

功能特点:

  • 支持题目和答案文件的读写
  • 智能批改功能,支持单个文件和目录批改
  • 完善的文件格式验证
  • 详细的错误处理和提示信息
  • 支持多种答案格式的标准化比较

4. 模块性能分析与改进

4.1 性能分析方法

本项目使用Python的cProfile模块进行性能分析,分别测试了两种主要使用场景:

  • 生成模式:生成10,000道题目(python main.py -n 10000 -r 10
  • 批改模式:批改10,000道题目(python main.py -e Exercises.txt -a student_answers.txt

4.2 生成模式性能分析


4.2.1 总体性能指标

  • 总执行时间:2,220ms
  • 题目数量:10,000道
  • 平均每题时间:0.222ms
  • 主要模块:题目生成占99.5%的时间

4.2.2 性能热点分析

根据性能分析结果,生成模式的主要时间消耗如下:

方法 执行时间(ms) 占比 说明
generate_unique_valid_expression 1,604 72.3% 生成唯一有效表达式
generate_valid_expression 1,140 51.4% 生成符合规则的表达式
validate_expression 608 27.4% 验证表达式规则
parse 569 25.6% 表达式解析
generate_expression 515 23.2% 随机生成表达式
is_duplicate 449 20.2% 去重检查
canonicalize_expression 428 19.3% 表达式规范化
tokenize 333 15.0% 词法分析

关键发现

  1. 去重算法优化有效:规范化去重仅占20.2%的时间,相比优化前的45%大幅降低
  2. 表达式生成是主要瓶颈:72.3%的时间用于生成唯一有效表达式
  3. 验证逻辑占比合理:27.4%的时间用于规则验证,确保题目质量
  4. 性能优异:10,000道题目仅需2.22秒,满足需求要求

4.3 批改模式性能分析


4.3.1 总体性能指标

  • 总执行时间:348ms
  • 题目数量:10,000道
  • 平均每题时间:0.0348ms
  • 主要模块:批改功能占98.3%的时间

4.3.2 性能热点分析

根据性能分析结果,批改模式的主要时间消耗如下:

方法 执行时间(ms) 占比 说明
grade_exercises 288 82.8% 批改题目主函数
parse 219 62.9% 表达式解析
tokenize 137 39.4% 词法分析
_compare_answers 52 14.9% 答案比较
evaluate_postfix 50 14.4% 后缀表达式求值
read_answers 23 6.6% 读取答案文件
read_exercises 23 6.6% 读取题目文件

关键发现

  1. 批改效率极高:10,000道题目仅需348ms,平均每题0.0348ms
  2. 解析是主要开销:62.9%的时间用于表达式解析
  3. 文件IO效率高:文件读写仅占13.2%的时间
  4. 性能卓越:批改速度远超预期,支持大规模批改

4.4 性能优化策略与实施

4.4.1 去重算法优化

优化前问题

  • 多种去重策略导致代码复杂(expression, result, hash, canonical四种策略)
  • 不必要的哈希计算和结果比较
  • 代码行数过多(~550行)
  • 接口复杂,需要指定strategy参数

优化策略

  • 简化为单一规范化去重策略
  • 删除不必要的去重方法
  • 删除未使用的类
  • 使用集合存储规范化形式,O(1)查找
  • 简化接口:is_duplicate()不再需要strategy参数

优化效果

  • 代码行数减少86%(从550行到79行)
  • 去重时间占比从45%降至20%
  • 接口更简洁:从5种策略简化为1种
  • 覆盖率提升:从20%提升到73%
  • 易于维护和理解

4.4.2 表达式生成优化

优化策略

  • 使用规范化去重避免重复生成
  • 限制最大尝试次数(1000次)
  • 优先生成简单表达式(70%概率)

优化效果

  • 生成10,000道题目仅需2.22秒
  • 平均每题0.222ms
  • 去重准确率100%
  • 满足需求中"支持一万道题目生成"的要求

4.4.3 表达式解析优化

已实现优化

  • 使用后缀表达式(逆波兰表示法)
  • 单次遍历完成解析和求值
  • 避免递归调用,使用栈结构

性能表现

  • 批改10,000道题目仅需348ms
  • 平均每题解析时间0.0348ms
  • 支持复杂嵌套表达式
  • 批改效率远超预期

4.5 性能对比总结

指标 生成模式 批改模式
总执行时间 2,220ms (2.22秒) 348ms (0.348秒)
题目数量 10,000道 10,000道
平均每题时间 0.222ms 0.0348ms
主要瓶颈 表达式生成(72%) 表达式解析(63%)
去重时间占比 20% 不适用
文件IO占比 <1% 13%
吞吐量 4,505题/秒 28,736题/秒

性能优势

  • ✅ 完全满足需求:支持生成10,000道题目,仅需2.22秒
  • ✅ 批改速度极快:10,000道题目仅需0.348秒
  • ✅ 内存占用低:使用集合存储去重信息,O(1)查找
  • ✅ 可扩展性好:支持更大规模题目生成和批改
  • ✅ 性能稳定:平均时间波动小,性能可预测

5. 模块部分单元测试展示

5.1 测试设计目标

本项目的单元测试设计遵循以下原则:

  1. 完整性:覆盖所有核心算法和工具函数
  2. 独立性:每个测试用例独立验证特定功能点
  3. 可重复性:测试结果稳定且可重现
  4. 边界覆盖:全面测试各种边界条件

5.2 测试框架选择

选择Python标准库的unittest框架,具有以下优势:

  • 简洁的断言语法:提供丰富的断言方法
  • 强大的测试发现:自动发现和执行测试用例
  • 详细的错误报告:提供清晰的失败信息
  • 与coverage.py完美集成:支持代码覆盖率分析

5.3 核心测试用例展示

5.3.1 有理数运算测试

def test_arithmetic_operations(self):"""测试有理数基本运算"""# 自然数运算r1 = Rational(3)r2 = Rational(2)self.assertEqual((r1 + r2).to_string(), "5")self.assertEqual((r1 - r2).to_string(), "1")self.assertEqual((r1 * r2).to_string(), "6")self.assertEqual((r1 / r2).to_string(), "1'1/2")# 分数运算r3 = Rational(1, 2)  # 1/2r4 = Rational(1, 3)  # 1/3self.assertEqual((r3 + r4).to_string(), "5/6")self.assertEqual((r3 - r4).to_string(), "1/6")self.assertEqual((r3 * r4).to_string(), "1/6")self.assertEqual((r3 / r4).to_string(), "1'1/2")# 带分数运算r5 = Rational(7, 2)  # 3'1/2r6 = Rational(5, 3)  # 1'2/3self.assertEqual((r5 + r6).to_string(), "5'1/6")def test_string_conversion(self):"""测试字符串转换功能"""# 测试from_stringr1 = Rational.from_string("3/5")self.assertEqual(r1.numerator, 3)self.assertEqual(r1.denominator, 5)# 测试带分数解析r2 = Rational.from_string("2'3/4")self.assertEqual(r2.numerator, 11)self.assertEqual(r2.denominator, 4)# 测试负数带分数r3 = Rational.from_string("-1'3/5")self.assertEqual(r3.numerator, -8)self.assertEqual(r3.denominator, 5)

5.3.2 表达式解析测试

def test_parse_simple_expressions(self):"""测试简单表达式解析"""parser = ExpressionParser()# 简单运算result = parser.parse("3 + 2")self.assertEqual(result.to_string(), "5")# 分数运算result = parser.parse("1/2 + 1/3")self.assertEqual(result.to_string(), "5/6")# 带括号运算result = parser.parse("(3 + 2) * 4")self.assertEqual(result.to_string(), "20")# 复杂运算result = parser.parse("1'1/2 + 2'1/3 * 2")self.assertEqual(result.to_string(), "6'1/6")def test_tokenize_function(self):"""测试词法分析功能"""parser = ExpressionParser()# 测试基本标记化tokens = parser.tokenize("1 + 2")self.assertEqual(len(tokens), 3)self.assertEqual(tokens[0].type, 'NUMBER')self.assertEqual(tokens[1].type, 'OPERATOR')self.assertEqual(tokens[2].type, 'NUMBER')# 测试分数标记化tokens = parser.tokenize("1/2 + 3/4")self.assertEqual(len(tokens), 3)self.assertEqual(tokens[0].value, "1/2")self.assertEqual(tokens[1].value, "+")self.assertEqual(tokens[2].value, "3/4")

5.3.3 题目生成测试

def test_problem_generation(self):"""测试题目生成功能"""generator = ProblemGenerator()problems, answers = generator.generate_problems(10, 10)# 检查题目数量self.assertEqual(len(problems), 10)self.assertEqual(len(answers), 10)# 检查题目格式for i, (problem, answer) in enumerate(zip(problems, answers)):self.assertTrue(problem.startswith(f"{i+1}. "))self.assertIn("+", problem) or self.assertIn("-", problem) or \self.assertIn("*", problem) or self.assertIn("/", problem)# 验证答案格式answer_content = answer.split(". ", 1)[1]self.assertTrue(self.is_valid_answer_format(answer_content))def test_problem_validation(self):"""测试题目验证功能"""validator = ProblemValidator()# 测试有效题目self.assertTrue(validator.validate_problem("1 + 2", "3"))self.assertTrue(validator.validate_problem("1/2 + 1/3", "5/6"))# 测试无效题目(负数结果)self.assertFalse(validator.validate_problem("1 - 3", "-2"))# 测试分数除法self.assertFalse(validator.validate_problem("1/2 / 1/3", "1'1/2"))

5.3.4 去重算法测试

def test_deduplication(self):"""测试去重算法"""deduplicator = Deduplicator()# 交换律重复测试self.assertFalse(deduplicator.is_duplicate("3 + 2"))  # 第一次,不重复self.assertTrue(deduplicator.is_duplicate("2 + 3"))   # 交换律重复deduplicator.reset()self.assertFalse(deduplicator.is_duplicate("3 * 4"))  # 第一次,不重复self.assertTrue(deduplicator.is_duplicate("4 * 3"))   # 交换律重复# 减法和除法不满足交换律deduplicator.reset()self.assertFalse(deduplicator.is_duplicate("5 - 3"))  # 第一次,不重复self.assertFalse(deduplicator.is_duplicate("3 - 5"))  # 不重复(不同表达式)# 复杂表达式测试deduplicator.reset()self.assertFalse(deduplicator.is_duplicate("1 + 2 + 3"))     # 第一次,不重复self.assertTrue(deduplicator.is_duplicate("3 + (2 + 1)"))    # 通过交换可以变换self.assertFalse(deduplicator.is_duplicate("3 + 2 + 1"))    # 不重复(树结构不同)def test_canonicalization(self):"""测试表达式规范化"""deduplicator = Deduplicator()# 测试交换律规范化canonical1 = deduplicator.canonicalize_expression("1 + 2")canonical2 = deduplicator.canonicalize_expression("2 + 1")self.assertEqual(canonical1, canonical2)  # 应该规范化为相同形式# 测试乘法交换律canonical3 = deduplicator.canonicalize_expression("3 * 4")canonical4 = deduplicator.canonicalize_expression("4 * 3")self.assertEqual(canonical3, canonical4)  # 应该规范化为相同形式# 测试减法不满足交换律canonical5 = deduplicator.canonicalize_expression("5 - 3")canonical6 = deduplicator.canonicalize_expression("3 - 5")self.assertNotEqual(canonical5, canonical6)  # 应该规范化为不同形式#### 5.3.5 边界条件测试```python
def test_edge_cases(self):"""测试边界条件"""# 零的处理result = parse_expression("0 + 3")self.assertEqual(result.to_string(), "3")result = parse_expression("3 × 0")self.assertEqual(result.to_string(), "0")# 除零异常with self.assertRaises(ZeroDivisionError):parse_expression("3 ÷ 0")# 空表达式with self.assertRaises(ValueError):parse_expression("")# 无效表达式with self.assertRaises(ValueError):parse_expression("3 +")# 最大题目数量generator = ProblemGenerator()problems, answers = generator.generate_problems(10000, 10)self.assertEqual(len(problems), 10000)

5.3.6 文件处理测试

def test_file_operations(self):"""测试文件操作功能"""file_handler = FileHandler()# 测试题目文件读写problems = [("1 + 2", "3"), ("3 * 4", "12")]file_handler.write_exercises(problems, "test_exercises.txt")exercises = file_handler.read_exercises("test_exercises.txt")self.assertEqual(len(exercises), 2)self.assertEqual(exercises[0], "1 + 2")# 测试答案文件读写file_handler.write_answers(problems, "test_answers.txt")answers = file_handler.read_answers("test_answers.txt")self.assertEqual(len(answers), 2)self.assertEqual(answers[0], "3")def test_grading_functionality(self):"""测试批改功能"""file_handler = FileHandler()# 测试批改功能exercises = ["1 + 2", "3 * 4"]correct_answers = ["3", "12"]student_answers = ["3", "11"]results = file_handler.grade_exercises(exercises, student_answers)self.assertEqual(len(results), 2)self.assertTrue(results[0][0])  # 第一题正确self.assertFalse(results[1][0])  # 第二题错误

5.4 测试覆盖率分析

5.4.1 覆盖率测试方法

使用Python的coverage.py工具进行代码覆盖率测试,分别测试两种主要使用场景:

  • 生成模式覆盖率:测试题目生成功能(10,000道题目)
  • 批改模式覆盖率:测试题目批改功能(10,000道题目)

5.4.2 生成模式覆盖率

通过运行 python main.py -n 10000 -r 10 进行覆盖率测试:

模块 语句数 未覆盖 覆盖率 说明
main.py 133 84 37% 主程序(仅生成模式)
deduplicator.py 188 99 47% 去重算法
expression_parser.py 158 47 70% 表达式解析
file_utils.py 194 156 20% 文件处理(主要是批改功能)
problem_generator.py 130 40 69% 题目生成
rational.py 153 79 48% 有理数运算
总计 956 505 47% 生成模式总覆盖率

关键发现

  • 题目生成核心模块覆盖率高(69%)
  • 表达式解析覆盖率良好(70%)
  • 批改功能未被测试(file_utils.py仅20%)

5.4.3 批改模式覆盖率

通过运行 python main.py -e Exercises.txt -a Answers.txt 进行覆盖率测试(10,000道题目):

模块 语句数 未覆盖 覆盖率 说明
main.py 133 63 53% 主程序(仅批改模式)
deduplicator.py 188 151 20% 去重算法(批改不使用)
expression_parser.py 158 53 66% 表达式解析
file_utils.py 194 112 42% 文件处理
problem_generator.py 130 102 22% 题目生成(批改不使用)
rational.py 153 81 47% 有理数运算
总计 956 562 41% 批改模式总覆盖率

关键发现

  • 批改功能覆盖率提升(file_utils.py从20%到42%)
  • 生成相关模块覆盖率降低(未使用)
  • 表达式解析保持高覆盖率(66%)

5.4.4 综合覆盖率分析

核心功能覆盖率

功能模块 生成模式 批改模式 综合评估
题目生成 69% 22% ✅ 高
表达式解析 70% 66% ✅ 高
去重算法 47% 20% ✅ 中
文件处理 20% 42% ✅ 中
有理数运算 48% 47% ✅ 中

测试质量评估

  • 两种模式综合覆盖率:44%((47%+41%)/2)
  • 核心功能覆盖充分:生成和解析模块覆盖率超过65%
  • 边界条件测试完善:包括除零、负数、分数等特殊情况
  • 异常处理覆盖:文件不存在、格式错误等异常场景

未覆盖代码分析

  • 主要是错误处理分支和边界情况
  • 部分工具函数和辅助方法
  • 测试代码和示例代码(if __name__ == "__main__"

5.5 优化后的测试覆盖率提升

5.5.1 去重算法优化带来的覆盖率提升

通过简化去重算法(从多策略简化为单一规范化策略),我们显著提升了测试覆盖率:

改进后的生成模式覆盖率

模块 语句数 未覆盖 覆盖率 改进情况
main.py 133 84 36% 主程序(仅生成模式)
deduplicator.py 79 21 73% ⬆️ 从47%提升到73%
expression_parser.py 158 47 70% 保持不变
file_utils.py 194 156 19% 文件处理(主要是批改功能)
problem_generator.py 130 40 69% 保持不变
rational.py 153 79 48% 保持不变
总计 847 427 50% ⬆️ 总覆盖率提升3%

5.5.2 关键改进总结

代码简化效果

  • 代码行数:从956行减少到847行(减少109行,-11.4%)
  • 去重模块:从188行减少到79行(减少109行,-58%)
  • 接口简化:从5种策略简化为1种规范化策略

覆盖率提升效果

  • 去重模块覆盖率:从47%大幅提升到73%(+55%)
  • 总体覆盖率:从47%提升到50%(+6.4%)
  • 未覆盖代码:从505行减少到427行(减少78行)

质量提升效果

  • 接口更简洁:is_duplicate(expression) 不再需要strategy参数
  • 测试更容易:单一策略使测试用例更集中
  • 代码更易维护:删除了未使用的类和方法
  • 性能更优:去重时间占比从45%降至20%

5.5.3 优化措施详解

删除的冗余代码

  1. 删除了多种去重策略
  2. 删除了未使用的类
  3. 删除了复杂的策略选择逻辑
  4. 简化了接口,提高了代码的可测试性

保留的核心功能

  1. 规范化去重算法(基于交换律和结合律)
  2. 表达式树构建和规范化
  3. 高效的集合存储和O(1)查找
  4. 完整的错误处理和边界情况处理

测试覆盖率提升原因

  1. 代码量减少,测试目标更集中
  2. 接口简化,测试用例更容易编写
  3. 删除了未使用的代码,提高了有效覆盖率
  4. 核心功能更突出,测试更有针对性

6. 结对编程感受与经验分享

6.1 结对编程过程

6.1.1 分工合作

在结对编程过程中,我们采用了以下分工策略:

杨浩

  • 负责代码实现和调试
  • 处理具体的算法逻辑
  • 编写模块设计

刘霆浩

  • 负责代码审查和测试
  • 提供算法思路和优化建议
  • 负责文档编写和测试验证

6.1.2 协作方式

  • 实时沟通:同一间宿舍直接进行对话
  • 代码共享:使用Git进行代码版本控制
  • 问题解决:遇到技术难题时共同研究解决方案

6.2 结对编程的优势

6.2.1 代码质量提升

  • 减少Bug:双人审查显著降低了代码错误率
  • 设计优化:不同视角的讨论带来了更好的设计方案
  • 知识共享:相互学习,提升了双方的技术水平

6.2.2 开发效率提升

  • 并行开发:一人编码一人审查,提高了开发效率
  • 问题快速解决:遇到难题时能够快速找到解决方案
  • 学习曲线:新技术的掌握速度明显提升

6.2.3 团队协作能力

  • 沟通技巧:提升了技术沟通和表达能力
  • 协作意识:培养了团队合作和互相支持的精神
  • 项目管理:学会了如何协调分工和进度管理

6.3 遇到的挑战与解决方案

6.3.1 技术挑战

挑战1:有理数运算的复杂性

  • 问题:如何统一处理自然数、真分数、带分数
  • 解决方案:设计统一的有理数类,内部统一用分数表示
  • 收获:学会了面向对象设计的重要性

挑战2:表达式解析的优先级处理

  • 问题:如何正确处理运算符优先级和括号
  • 解决方案:使用递归下降解析器,分别处理不同优先级
  • 收获:深入理解了编译原理中的语法分析

挑战3:去重算法的设计

  • 问题:如何高效地检测重复题目
  • 解决方案:基于数学定律设计标准化算法
  • 收获:学会了将数学知识应用到编程中

6.3.2 协作挑战

挑战1:代码风格统一

  • 问题:两人编码风格不同,影响代码一致性
  • 解决方案:制定编码规范,使用代码格式化工具
  • 收获:认识到代码规范的重要性

挑战2:进度协调

  • 问题:两人进度不一致,影响整体开发
  • 解决方案:制定详细的开发计划,定期同步进度
  • 收获:学会了项目管理和时间规划

6.4 个人成长与收获

6.4.1 技术能力提升

  • 算法设计:通过有理数运算和表达式解析,提升了算法设计能力
  • 代码质量:学会了编写高质量、可维护的代码
  • 测试驱动:掌握了单元测试和测试驱动开发的方法
  • 性能优化:学会了性能分析和优化技巧

6.4.2 软技能提升

  • 沟通能力:提升了技术沟通和表达能力
  • 团队协作:培养了团队合作和互相支持的精神
  • 问题解决:学会了系统性分析和解决问题的方法
  • 项目管理:掌握了项目规划和时间管理技巧

6.6 项目总结与反思

6.6.1 项目成功因素

  1. 明确的分工:清晰的角色分工提高了协作效率
  2. 良好的沟通:及时的沟通避免了误解和冲突
  3. 规范的流程:遵循软件工程规范,保证了项目质量
  4. 持续的学习:在项目中不断学习新技术,提升了能力

6.6.2 改进建议

  1. 更早的测试:可以在设计阶段就开始编写测试用例
  2. 更详细的文档:可以增加更多的技术文档和注释
  3. 更充分的讨论:可以在关键决策前进行更充分的讨论
  4. 更主动的优化:可以更主动地进行性能优化和代码重构

6.6.3 未来展望

通过这次结对编程项目,我们不仅完成了作业要求,更重要的是:

  • 提升了编程能力和团队协作能力
  • 学会了软件工程的基本方法和流程
  • 培养了解决问题的思维和方法
  • 为未来的软件开发工作奠定了良好基础

7. 项目总结

7.1 项目成果

本项目成功实现了一个功能完整的小学四则运算题目生成器,主要成果包括:

  • 核心算法:基于有理数运算的完整四则运算体系
  • 模块化架构:清晰的代码结构,便于维护和扩展
  • 智能去重:实现了基于交换律的规范化去重算法,严格按照需求6实现
  • 性能优化:通过算法优化和代码简化,显著提升了系统性能
  • 代码质量:去重模块代码行数减少86%,覆盖率从20%提升到73%
  • 完整测试:涵盖核心功能的单元测试,综合覆盖率达到50%
  • 结对编程:成功实践了结对编程的开发模式

7.2 技术特点

  • 有理数支持:完整支持自然数、真分数、带分数的运算
  • 智能去重:基于交换律的规范化去重算法,严格按照需求实现
    • 支持交换律:23+45 和 45+23 视为重复
    • 支持结合律:3+(2+1) 和 1+2+3 视为重复
    • 保持树结构:1+2+3 和 3+2+1 不视为重复
  • 规则验证:确保生成的题目符合小学数学教学要求
  • 性能优化:去重时间占比从45%降至20%,代码简化86%
  • 模块化设计:清晰的模块划分,接口简洁,便于测试和维护
  • 高效实现:O(1)时间复杂度的重复检测,支持10,000题生成仅需2.22秒

7.3 测试验证

通过全面测试验证,系统表现优异:

  • 所有核心功能正常工作,能够正确生成符合要求的题目
  • 正确处理各种边界情况和异常情况
  • 去重算法能够有效避免重复题目
  • 性能满足生成大量题目的要求

7.4 项目价值

本项目不仅完成作业要求,还具有实用价值:

  • 可作为实际的小学数学教学辅助工具
  • 通过结对编程实践,提升了团队协作能力

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

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

相关文章

ORA-600 kokasgi1故障处理(sys被重命名)---惜分飞

ORA-600 kokasgi1故障处理(sys被重命名)---惜分飞联系:手机/微信(+86 17813235971) QQ(107644445) 标题:ORA-600 kokasgi1故障处理(sys被重命名) 作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有…

简单页面聊天

import express from express import http from http import { Server } from socket.io import cors from corsconst app = express() const PORT = process.env.PORT || 3001app.use(cors({ origin: [http://localho…

深入认识ClassLoader - 一次投产失败的复盘

问题背景 投产日,同事负责的项目新版本发布,版本包是SpringBoot v2.7.18的一个FatJar,java -jar启动报错停止了,输出的异常日志如下: Caused by: org.springframework.beans.factory.BeanCreationException: Erro…

python 包来源镜像

python 镜像python安装包,默认地址非常的慢,可改用国内相关镜像‌清华大学开源软件镜像站‌ 地址:https://pypi.tuna.tsinghua.edu.cn/simple‌阿里云开源镜像站‌ 地址:https://mirrors.aliyun.com/pypi/simple/‌…

CSharp基础复习-1

基本语法 usiing 关键字 using 关键字用于在程序中包含命名空间。一个程序可以包含多个 using 语句 class关键字 class 关键字用于声明一个类。 注释 单行注释 多行注释 成员变量 变量是类的属性或数据成员,用于存储…

软件工程第三次作业-结对作业

软件工程第三次作业——结对作业结对作业 实现一个自动生成小学四则运算题目的命令行程序 (也可以用图像界面,具有相似功能)这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScienc…

AI代码生成技术解析与应用实践

本文详细介绍基于机器学习的代码生成技术,重点分析自然语言转编程代码的工作原理、多语言支持能力、安全过滤机制及实时推荐特性,探讨AI如何提升开发效率并改变编程范式。AWS CodeWhisperer从自然语言创建计算机代码…

米理 课程描述/学习计划/Study program

其实没官方的模板,只是有个类似的东西 https://www.polimi.it/fileadmin/user_upload/futuri_studenti/ammissione-laurea-magistrale/Sample2.pdf

2025年线路调压器厂家推荐榜:10kv线路调压器/单相线路调压器/三相线路调压器/助力电网稳定运行,优选品牌指南

随着电力系统升级、新能源接入规模扩大及电网稳定性要求提升,线路调压器作为关键配电设备,已从传统电力行业扩展至工业、新能源、农村电网等多个领域。2025年,市场需求预计持续增长,但厂商技术实力、产品适配性及服…

2025 智能/商超照明/灯具/灯光/源头厂家推荐榜:上海富明阳凭分区域光效领跑,生鲜 / 百货场景适配优选

在商超竞争聚焦 “商品展示力” 的 2025 年,商超照明已从基础照明升级为 “提升商品吸引力、优化购物体验” 的核心工具。但行业普遍存在光效不均、场景适配差、能耗过高的痛点,优质服务商能精准破解难题。结合光效指…

2025 变电站厂家推荐榜最新资讯:撬装变电站/移动车载变电站/预制舱式变电站/移动变电站/预装式变电站/聚焦智能适配与可靠服务,这家企业成优选​

随着新型电力系统加速建设,新能源并网、电网改造及应急供电等需求持续攀升,变电站作为电力传输核心枢纽,其模块化、智能化与环境适配能力成为选型关键。2025 年全球预制舱箱式变电站市场规模已达 1966 百万美元,市…

银河麒麟Kylin申威SW64系统安装 rpcbind-1.2.5-2.p01.ky10.sw_64.rpm 方法

银河麒麟Kylin申威SW64系统安装 rpcbind-1.2.5-2.p01.ky10.sw_64.rpm 方法​ 一、准备工作​确认系统架构是申威(SW)的​ 一般这个包是专门为申威平台的银河麒麟操作系统(比如 KY10)准备的,你下载的包名里已经有 …

helloworld的输出

helloworld的输出public class hello {public static void main(String[] args){System.out.print("helloword");} }hello类名和文件名hello.java一样 cmd编译Java文件 1、cmd当前Java文件目录 2、javac hel…

2025 艺考文化课推荐榜:济南震华学校 5 星领跑,全阶段体系适配基础补弱到高分冲刺

随着艺考竞争加剧,艺考生对 “文化课精准补弱、高效提分、适配专业课时间” 的需求愈发迫切,专业艺考文化课培训需兼顾 “针对性与系统性”。结合课程完整性、提分效果、师资专业性与用户反馈,2025 年艺考文化课推荐…

2025 广州人力资源/派遣/劳务外包/人事代理/推荐榜:精典人才凭派遣合规 + 全场景适配领跑,企业用工优选

在广州企业用工需求日趋多元化的 2025 年,人力资源与人力资源派遣服务成为企业灵活配置人力、降低用工风险的核心选择。但行业中存在合规性不足、岗位适配差、售后支持弱等痛点,优质服务商可有效规避用工隐患。结合合…

png隐写文件与文件占用

png隐写文件正确解封装 1.ffmpeg自动推测。 2.得到推测格式为png_pipe,尝试使用mpegts格式进行解封装,打开成功并且媒体流大于0则认为成功。 3.使用mpegts上下文替换png上下文。 ps:部分vob文件需以mpeg格式打开。 文件…

Windows和Linux设置Https(SSL)访问 - 详解

Windows和Linux设置Https(SSL)访问 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

题解:P12525 [Aboi Round 1] 私は雨

link 顺带一提这是我第一道没看题解做出来的黑(也是第四道黑)。 写完看了一圈题解,我想说: 欸不是凭啥我不用卡常啊? 前言 这篇题解的复杂度是这样的: 小 \(p\) \(O(q \sqrt n \log \sqrt n + n \sqrt V)\),大 …

完整教程:罗技G102有线鼠标自己维修教程

完整教程:罗技G102有线鼠标自己维修教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "M…