结对作业

李海婷,学号3224004192,GitHub仓库链接:https://github.com/Sleepy-li/3224004192

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class56-Grade2024-CS
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class56-Grade2024-CS/homework/15694
这个作业的目标 实现一个自动生成小学四则运算题目的命令行程序

PSP表格:

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

一、效能分析
一开始没有设置分母的取值,所以刚开始程序生成不了想要的结果,于是在除法判断出增加了除数!=0的校验,代码成功运行。
image

image
使用 Python 内置cProfile进行性能分析,设置sort='cumtime',按照累计执行时间排序。运行生成 10000 道题,从输出结果可以看出,get_normalized_key()累计耗时最高,是整个程序的性能瓶颈。该函数负责递归遍历表达式树生成规范化 key 用于查重,每次生成候选表达式都要调用;随着题目数量增加,哈希集合越来越大,key 生成与哈希比对开销持续上升。其次消耗较大的是eval()函数,用于递归计算表达式的值,校验减法、除法约束。

二、设计实现过程
1、代码组织、模块、类、函数结构
整体分为五大模块:分数格式化模块、表达式树节点类、表达式生成模块、查重模块、批改模块、命令行入口。

类:ExprNode
作用:用二叉树表示算术表达式。

  • 属性:val(叶子节点,Fraction 分数对象);op运算符;left左子树;right右子树。
  • 成员方法:
  1. is_leaf():判断是否是叶子(数字节点,不是运算符)
  2. eval():递归计算当前表达式的值,返回 Fraction
  3. to_string(need_bracket):递归生成带括号的表达式字符串,自动处理括号优先级,输出题目文本
  4. get_normalized_key():递归生成规范化 key,用于去重;+和*将左右 key 排序,交换操作数视为同一道题

全局函数列表

  1. format_frac(f:Fraction):将 Fraction 对象转为作业要求的字符串(2'3/8、3/5、自然数)
  2. parse_frac(s:str):解析带分数字符串,转回 Fraction(批改模块用)
  3. gen_number(r_max):随机生成自然数或者真分数,作为叶子节点
  4. gen_expr(op_count, r_max):递归生成一棵合法表达式二叉树,核心生成函数
  • 递归终止条件:op_count=0,返回叶子数字节点
  • op_count>0:拆分运算符数量,递归生成左、右子树
  • 循环随机选运算符,校验约束:减法左≥右;除法除数≠0、结果 0<res<1
  1. generate_exercises(count, r_max):循环生成指定数量题目,调用 gen_expr,利用集合保存规范化 key,去重,收集题目字符串和答案。
  2. grade_exercise(ex_file, ans_file, out_file):批改模块,读取 Exercises.txt、Answers.txt,逐题计算标准答案,比对用户答案,输出 Grade.txt
  3. main():命令行参数解析,分发到出题模式 / 批改模式;程序入口。

模块之间关系
main()
├─ 出题模式:调用 generate_exercises()
│ ├─ gen_expr() 生成表达式树 ExprNode
│ │ └─ gen_number() 生成数字叶子
│ └─ ExprNode.get_normalized_key() 查重;ExprNode.to_string()生成题目文本;format_frac格式化答案
└─ 批改模式:调用 grade_exercise()
└─ parse_frac() 解析分数字符串,计算、比对答案

流程图:
Mermaid

三、代码说明
关键代码说明:
关键代码1:ExprNode 类(表达式二叉树,核心数据结构)
image

解释:二叉树保存表达式结构。get_normalized_key是实现作业要求去重逻辑的核心。
关键代码2:gen_expr,递归生成合法表达式
image

解释:递归构造表达式树,随机选运算符,循环校验规则。不满足约束就重新随机运算符,直到找到合法运算符。
关键代码3:批改函数 grade_exercise
image

解释:读取文件,解析自定义带分数格式,转换为 python 表达式计算标准答案;比对用户答案,按要求格式输出。

四、测试运行(直接在终端输入命令)
示例1:正常出题
命令:.\Myapp.exe -n 10 -r 10
输出:Exercises.txt、Answers.txt,共 10 道不重复四则运算题;每题运算符≤3;减法无负数,除法结果为真分数。
截图:image
image
答案:image
image

示例2:参数缺失校验
命令:.\Myapp.exe -n 10
预期:程序打印帮助信息,不生成题目。
image

示例3:大批量生成
命令:.\Myapp.exe -n 10000 -r 20
预期:成功生成一万道不重复题目与答案文件。
image

image

示例4:批改功能
命令:.\Myapp.exe -e Exercises.txt -a Answers.txt
输出 Grade.txt 示例:
image
image

五、项目小结
过程中会出现一些问题,但我觉得我自己解决,不能解决的问题我也上网咨询过了,通过本次结对项目的实践,我体会到了不一样的写项目过程,虽然两个人组队会更好的让自己适应以后工作后会出现的合作,但我还是喜欢自己一个人做事。

最后的PSP表格:

PSP2.1 Personal Software Process Stages 实际耗时(分钟)
Planning 计划 300
· Estimate · 估计这个任务需要多少时间 300
Development 开发 415
· Analysis · 需求分析 (包括学习新技术) 45
· Design Spec · 生成设计文档 20
· Design Spec · 设计复审 30
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 60
· Design · 具体设计 60
· Coding · 具体编码 120
· Code Review · 代码复审 35
· Test · 测试(自我测试,修改代码,提交修改) 45
Reporting 报告 125
· Test Repor · 测试报告 60
· Size Measurement · 计算工作量 20
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 45
· 合计 540
posted @ 2026-09-22 20:53  李海婷  阅读(12)  评论(0)    收藏  举报