第三周作业

李兆希(3124004099)https://github.com/LZX2025/SoftwareEngineeringWork/tree/main/Week3
杨旭东(3124004109)

代码组织

项目分为三个文件:
fraction_utils.py 分数格式化、词法分析、表达式解析
generator.py 表达式树、随机生成、去重、转字符串、批量生成
Myapp.py 命令行参数解析、生成模式、判分模式、文件读写

关键代码

表达式生成与约束检查

def gen_expr(max_ops: int, r: int, depth: int = 0) -> Node:
    if max_ops == 0:
        return Node(val=random_leaf(r))
    left_ops = random.randint(0, max_ops - 1)
    right_ops = max_ops - 1 - left_ops
    left = gen_expr(left_ops, r, depth + 1)
    right = gen_expr(right_ops, r, depth + 1)
    ops = ["+", "−", "×", "÷"]
    random.shuffle(ops)
    for op in ops:
        if op == "+":
            return Node(op, left, right, left.val + right.val)
        elif op == "−":
            if left.val >= right.val:
                return Node(op, left, right, left.val - right.val)
        elif op == "×":
            return Node(op, left, right, left.val * right.val)
        elif op == "÷":
            if right.val != 0 and 0 < left.val < right.val:
                return Node(op, left, right, left.val / right.val)
    raise ValueError("无法生成满足约束的表达式")

表达式转字符串

def expr_to_string(node: Node) -> str:
    if node.op is None:
        return format_fraction(node.val)
    left_str = expr_to_string(node.left)
    right_str = expr_to_string(node.right)
    if node.left.op is not None and precedence(node.left.op) < precedence(node.op):
        left_str = f"({left_str})"
    if node.right.op is not None:
        rp = precedence(node.right.op)
        cp = precedence(node.op)
        if rp < cp:
            right_str = f"({right_str})"
        elif rp == cp:
            if not ((node.op == "+" and node.right.op == "+") or
                    (node.op == "×" and node.right.op == "×")):
                right_str = f"({right_str})"
    return f"{left_str} {node.op} {right_str}"

性能分析

已生成 1000 道题目:Exercises.txt, Answers.txt
         205277 function calls (192542 primitive calls) in 0.074 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
5028/1000    0.006    0.000    0.032    0.000 generator.py:42(gen_expr)
    14248    0.005    0.000    0.008    0.000 random.py:245(_randbelow_with_getrandbits)
     8206    0.003    0.000    0.009    0.000 random.py:335(randint)
     4014    0.003    0.000    0.004    0.000 fraction_utils.py:4(format_fraction)
      124    0.003    0.000    0.003    0.000 {built-in method nt.stat}
     24/1    0.003    0.000    0.074    0.074 {built-in method builtins.exec}
     3014    0.003    0.000    0.011    0.000 generator.py:16(random_leaf)
5028/1000    0.002    0.000    0.004    0.000 generator.py:83(norm)
        3    0.002    0.001    0.002    0.001 {built-in method _imp.create_dynamic}
        1    0.002    0.002    0.046    0.046 generator.py:133(generate)
5028/1000    0.002    0.000    0.005    0.000 generator.py:107(expr_to_string)
...

从 cProfile 结果看,消耗最大的函数是:

generator.gen_expr:递归生成表达式树,需要反复尝试满足减法非负、除法为真分数等约束。

改进思路
减少无效尝试:在 gen_expr 中提前判断运算符是否满足约束,不满足则直接换下一个运算符,避免大量异常。

测试用例

编号 测试内容 输入/操作 预期结果
1 生成 10 道 10 以内题目 python Myapp.py -n 10 -r 10 生成 Exercises.txt 和 Answers.txt,各 10 行
2 缺少 -r 参数 python Myapp.py -n 5 报错并提示帮助信息
3 -r 1 边界 python Myapp.py -n 5 -r 1 生成 5 道题,数值均为 0
4 运算符个数不超过 3 检查生成的题目 每行运算符 ≤ 3
5 减法不出现负数 检查生成题目及计算过程 所有减法结果 ≥ 0
6 除法结果为真分数 检查生成题目 除法结果 0 < 结果 < 1
7 题目不重复 生成 100 道题,检查去重 无重复等价题目
8 分数格式 检查含带分数的题目 格式如 2’3/8
9 判分模式正确统计 构造 TestEx.txt 与 TestAns.txt,运行 python Myapp.py -e TestEx.txt -a TestAns.txt Grade.txt 输出 Correct/Wrong 及题号
10 判分模式错题识别 故意写错部分答案 错题题号出现在 Wrong 中

PSP

PSP Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
· Estimate · 估计这个任务需要多少时间 5 5
Development 开发
· Analysis · 需求分析(包括学习新技术) 10 15
· Design Spec · 生成设计文档 20 25
· Design Review · 设计复审(和同事审核设计文档) 10 5
· Coding Standard · 代码规范(为目前的开发制定合适的规范) 5 5
· Design · 具体设计 20 30
· Coding · 具体编码 120 120
· Code Review · 代码复审 10 20
· Test · 测试(自我测试,修改代码,提交修改) 10 15
Reporting 报告
· Test Report · 测试报告 30 40
· Size Measurement · 计算工作量 10 10
· Postmortem & Process Improvement Plan · 事后总结,并提出过程改进计划 5 5
合计
posted @ 2026-09-21 21:37  LZX2024  阅读(11)  评论(0)    收藏  举报