结对项目
结对项目
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience/homework/13479 |
这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
github连接: | LancyPluto/3123004789 at 结对项目 |
成员一 | 蓝毅 3123004789 |
成员二 | 杨腾竣 3123004809 |
一、psp表格如下
Process Stages | Process Stages (中文) | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 25 |
· Estimate | · 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 420 | 360 |
· Analysis | · 需求分析 (包括学习新技术) | 120 | 120 |
· Design Spec | · 生成设计文档 | 15 | 20 |
· Design Review | · 设计复审 | 100 | 120 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 90 | 90 |
· Design | · 具体设计 | 60 | 90 |
· Coding | · 具体编码 | 400 | 420 |
· Code Review | · 代码复审 | 90 | 100 |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 80 | 100 |
· Test Report | · 测试报告 | 40 | 70 |
· Size Measurement | · 计算工作量 | 20 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 10 |
· 合计 | 1625 | 1675 |
二、计算模块接口的设计与实现过程
2.1 程序整体结构
2.1.1 核心模块
模块名称 | 主要函数 | 功能职责 |
---|---|---|
命令行解析模块 | main() |
解析 -n -r (生成模式)和 -e -a (批改模式)参数,作为程序入口 |
表达式构建模块 | generate_expr(max_ops, r) random_number(r) |
随机生成合法的四则运算表达式树(含自然数/真分数),控制运算符数、不产生负数、不非法除法 |
运算与格式化模块 | eval() (各类 Expr) serialize() frac_to_str() |
计算表达式结果,输出标准格式(整数、真分数、带分数) |
去重校验模块 | canonicalize(expr) |
将表达式转换为唯一结构字符串(对 commutative 运算排序)用于避免题目重复 |
题目生成模块 | generate_unique_exercises(count, r) write_files() |
批量生成不重复题目与答案,并写入 Exercises.txt 和 Answers.txt |
答案解析模块 | parse_fraction(s) |
将字符串格式的整数/真分数/带分数解析为 Fraction 对象 |
题目求值模块 | evaluate_exercise(expr_line) |
将题目字符串解析并求出正确答案(支持混合数替换、×÷转换) |
批改统计模块 | grade(ex_file, ans_file) |
对比答案,统计对错编号,生成 Grade.txt (Correct/ Wrong 格式) |
2.2 算法核心
2.2.1 核心思想
Ⅰ. 题目生成算法
思想核心:随机生成表达式树 + 约束条件筛选 + 去重
(1)表达式树生成
- 通过递归构建表达式树(
Expr
类层次结构)。 - 节点类型包括:
Num
(叶节点,表示自然数或真分数)BinOp
(中间节点,表示 +, −, ×, ÷ 运算)
(2)运算约束条件
a - b
时必须满足a ≥ b
(防止负数)a ÷ b
时结果必须在(0, 1)
之间(确保是真分数)- 运算符数量 ≤ 3
- 数值范围由参数
-r
控制
(3)去重规则(核心难点)
-
对于
+
和×
,题目视为可交换:a + b
≡b + a
-
使用
canonicalize(expr)
生成表达式的规范化字符串:
- 同构结构 + commutative 运算排序
- 如
(+:N:2,N:3)
与(+:N:3,N:2)
→ 统一为同一键值
-
以哈希表 (
set
) 去重。
(4)输出格式化
- 使用
serialize()
生成表达式字符串(含括号) - 使用
frac_to_str()
输出真分数 / 带分数格式 - 同步生成
Exercises.txt
与Answers.txt
Ⅱ. 批改算法
思想核心:计算真实答案 + 比对学生答案 + 输出统计
(1)解析题目并计算正确答案
- 替换符号:
× → *
÷ → /
2'3/5 → (2 + 3/5)
- 使用
Fraction
精确计算避免浮点误差。
(2)解析学生答案
- 将输入字符串(整数、真分数、带分数)解析成
Fraction
对象。
(3)比较结果
- 若
Fraction
值相等 → 正确 - 否则 → 错误
- 记录题号(从 1 开始)
2.2 算法流程图
三、计算模块性能优化
优化方向 | 具体措施 | 改进思路 |
---|---|---|
去重机制 | 将表达式结构的 canonical key 缓存在 set 中,使用 tuple 表示结构 |
避免字符串拼接与重复生成 |
表达式生成 | 使用迭代控制运算深度而非纯递归 | 减少函数调用开销 |
Fraction 计算 | 延迟求值,仅在最终输出时化简 | 避免中间节点重复计算 |
I/O 写入 | 采用一次性批量写入 | 减少文件 I/O 系统调用次数 |
四、代码说明
二元操作类 BinOp
:
- 这个类也继承自
Expr
,用于表示带有两个操作数和一个操作符的二元运算(如a + b
)。它包含一个运算符(op
)和两个操作数(left
和right
)。eval()
方法根据运算符对两个操作数执行运算,serialize()
方法将其格式化为字符串表示。
递归生成表达式 generate_expr
:
- 这个函数递归生成包含max_ops运算符的数学表达式。它通过递归调用build()函数来生成运算表达式,最终返回一个二元运算对象(BinOp)。表达式中的操作符有加、减、乘、除,且会遵循一些约束:
- 减法不能生成负数。
- 除法的结果必须是一个真分数(即结果在 0 和 1 之间)。
五、测试运行
命令行输入:
python test.py -n 10 -r 10
生成题目:
答案:
结果:
经验算,结果全部正确,说明程序运行正常。
六、项目小结
1.项目概述
本项目实现了一个小学四则运算题自动生成与批改程序,包括:
- 随机生成题目(整数、分数、带分数)
- 自动计算答案
- 去重与格式化输出
- 批改答案并输出统计结果
通过命令行参数可选择生成模式或批改模式。
2.项目成果
功能完整:题目生成、答案计算、批改一体化
结构清晰:面向对象设计,模块独立
细节完善:避免负数、控制除法真分数、格式化输出
3.问题与教训
输入与异常处理不够完善
难度控制单一
文件名与路径较固定
启示:提前统一接口与数据格式;早期测试可避免集中调试。