软件工程结对项目 小学四则运算题目生成与自动批改

项目 内容
所属课程 软件工程
作业要求 结对项目
项目成员 陈昱绰(3123004519)、陈鹏旭(3124004200)
项目地址 GitHub 仓库
程序下载 源码与 Windows 程序包

本项目用 Python 实现小学四则运算题目生成和自动批改。开发与复核使用了 AI 工具辅助,测试结果和性能数据均来自实际运行。

一、PSP 时间表

下表为工作量估算,单位是分钟。计划、开发和报告按各自子项汇总。

PSP2.1 工作内容 预估耗时 参考耗时(估算)
Planning 计划 10 10
· Estimate 估计任务所需时间 10 10
Development 开发 140 155
· Analysis 需求分析 25 30
· Design Spec 设计文档 10 10
· Design Review 设计复审 10 10
· Coding Standard 代码规范 5 5
· Design 具体设计 15 15
· Coding 编码与修改 25 30
· Code Review 代码复审 20 20
· Test 运行与测试 30 35
Reporting 报告 30 35
· Test Report 测试报告 15 20
· Size Measurement 计算工作量 5 5
· Postmortem & Process Improvement Plan 总结与改进计划 10 10
合计 180 200

二、需求理解

程序分为生成和批改两种模式。生成时,-n 指定题目数量,-r 指定操作数和分数分母的上限,不包含上限本身。题目写入 Exercises.txt,对应答案写入 Answers.txt。批改时,用 -e、-a 分别指定题目文件和学生作答文件,结果保存到 Grade.txt。

每道题最多 3 个运算符,计算过程中不能出现负数,除法结果必须是真分数。这里要检查每一步运算,不能只看最后的答案。

去重比较容易理解错。按题目规定,3+(2+1) 和 1+2+3 重复,1+2+3 与 3+2+1 不重复,所以不能直接按答案判断。

三、程序设计

程序按职责拆成四个部分:

文件 主要作用
Myapp.py 读取参数,选择生成或批改模式,处理错误提示
quiz/model.py 分数处理、表达式树、题面输出和表达式解析
quiz/generate.py 随机生成合法题目并去重
quiz/files.py 文件读写、题号检查和批改统计

表达式用二叉树保存,叶子是数,其他节点是运算符。生成时先确定运算符数量,再递归创建左右子树。

减法把较大的子表达式放在左边。除法把较小的正数放在左边,无法满足要求时改用其他运算。每生成一道题就检查是否重复,直到数量够用。

四、关键实现

1. 分数计算

分数统一使用 Python 标准库中的 Fraction,避免将分数转成小数后产生误差。

from fractions import Fraction

result = Fraction(1, 6) + Fraction(1, 8)
# 结果为 7/24

输出时把假分数转成带分数,如 19/8 写成 2'3/8。批改按数值比较,6/4 和 1'1/2 都可以判对。

2. 题目去重

去重的关键代码如下:

def key(self) -> tuple:
    if not self.op:
        return ("n", self.value.numerator, self.value.denominator)

    left, right = self.left.key(), self.right.key()
    if self.op in ("+", "*") and right < left:
        left, right = right, left
    return (self.op, left, right)

加法和乘法的左右键按固定顺序排列,减法和除法保持原顺序。这样得到的键既能处理交换顺序的情况,也保留了原来的树形结构。把键放入集合,就可以查重。

3. 括号与批改

括号需要保留原来的运算结构,尤其是同优先级的右子表达式。例如 1+(2+3) 的括号不能直接省掉。

批改时重新解析题目,再计算答案。解析器按加减、乘除、数字或括号分层处理,3/4 作为一个分数读取。

五、性能分析

性能分析工作量估算为 35 分钟。下面是程序实测时间。

在 macOS arm64、Python 3.9.6 下,固定 r=10 和种子 20261009,对同一批题目分别用列表和集合查重,各跑三次取中位数。

题目数量 列表查重耗时(秒) 集合查重耗时(秒)
100 0.007026 0.008159
1000 0.157539 0.069600
10000 10.710707 1.792698

性能分析图

一万道题时,集合查重的优势比较明显,耗时约为列表方案的六分之一。一百道题时差别不大,集合还略慢一些。列表方案用于对照,结果也会受后台负载影响。

cProfile 显示,主要时间花在建树和生成操作数上。另一轮运行中,一万道题的生成、写文件和批改分别用了 1.187 秒、0.191 秒和 0.892 秒。

六、测试结果

自动化测试共 38 项,全部通过。下面列出主要场景:

序号 测试内容 预期结果 结果
1 -n 10 -r 10 生成 10 道题及对应答案 通过
2 缺少 -r 显示帮助和参数错误 通过
3 -n 0、-r 0 拒绝无效参数 通过
4 1/6 + 1/8 得到 7/24 通过
5 1/2 ÷ 3/4 得到 2/3 通过
6 加法或乘法交换两侧 判为重复 通过
7 3+(2+1) 与 1+2+3 判为重复 通过
8 1+2+3 与 3+2+1 判为不重复 通过
9 多个范围和随机种子 数值范围、运算符数量和中间结果合法 通过
10 生成一万道题 数量正确、题目不重复、答案一致 通过
11 使用生成答案进行批改 全部正确 通过
12 只改错第 2、5 题 错题号恰为 2、5 通过
13 未约分的等值答案 按数值判对 通过
14 空白作答或题号错位 分别判错或提示编号错误 通过

除这些用例外,还把生成的题面重新解析并计算答案。独立 AI 复核检查了一万道题和 32 种括号组合,均通过,日志放在 reports/agent-review/。

实测运行记录

上图由实测日志整理,代理复核用时 192.15 秒。

Windows 打包后出现过中文输出编码错误,设置 UTF-8 后解决。修复后的 exe 也通过了一万道题的生成和批改测试。

七、运行方法

在项目目录执行:

# 生成 10 道题
python3 Myapp.py -n 10 -r 10

# 生成一万道题
python3 Myapp.py -n 10000 -r 10 --seed 20261009

# 批改作答
python3 Myapp.py -e Exercises.txt -a Answers.txt

# 运行测试
python3 tools/check.py

Windows 使用 Python 版时,可将 python3 换成 py -3;也可以下载 Myapp.exe,在终端中使用相同参数。再次生成题目会更新同名文件,需要保留多批题目时可指定 --output-dir。

八、项目小结

这次项目中,去重规则和括号处理比四则运算本身更值得注意。如果只看答案是否正确,很容易忽略题目结构已经变化。用表达式树处理后,这几部分比较容易联系起来。

目前程序能完成生成和批改,但题目难度还是随机的,也没有做图形界面。范围很小时,生成大量不同题目还需要较多尝试。这些地方后面还可以继续改进。

posted @ 2026-10-09 13:46  Cy3807  阅读(3)  评论(0)    收藏  举报