结对项目
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 软件工程 |
| 这个作业要求在哪里 | 作业要求 |
| 这个作业的目标 | 学习项目协作开发过程 |
GitHUb代码仓库:👨💻 [https://github.com/xiu-ye/zuoye2]
作者:莫晓淇3223004213 张荣辉31232004162
PSP:
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 40 | 60 |
| Estimate | 估计这个任务需要多少时间 | 60 | 90 |
| Development | 开发 | 360 | 420 |
| Analysis | 需求分析 (包括学习新技术) | 60 | 80 |
| Design Spec | 生成技术文档 | 30 | 35 |
| Design Review | 设计复审 | 20 | 30 |
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 30 |
| Design | 具体设计 | 50 | 70 |
| Coding | 具体编码 | 190 | 220 |
| Code Review | 代码复审 | 40 | 50 |
| Test | 测试(自我测试,修改代码,提交修改) | 40 | 40 |
| Reporting | 报告 | 40 | 50 |
| Test Repor | 测试报告 | 20 | 30 |
| Size Measurement | 计算工作量 | 15 | 25 |
| Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 20 | 30 |
| Total | 合计 | 1005 | 1260 |
1.代码组织
计算模块的核心功能是生成数学表达式、计算表达式的值以及验证表达式的合法性。代码组织如下:
-
类:
Number:封装整数和分数,提供分数的简化、字符串表示和分数转换功能。ExpressionNode:表示表达式树的节点,支持叶子节点(数字)和非叶子节点(操作符和左右子树)。
-
函数:
generate_expression:递归生成随机的数学表达式树。evaluate:递归计算表达式树的值。is_valid:验证表达式树的合法性。validate_operation:验证特定操作符的合法性(如减法和除法的约束)。generate_number:生成随机数(整数或分数)。canonical_form:将表达式树转换为规范形式,避免重复表达式。format_expression:将表达式树格式化为带括号和空格的字符串。
类与函数的关系
Number和ExpressionNode是数据结构的核心,分别表示数字和表达式节点。generate_expression使用ExpressionNode构建表达式树,并调用generate_number生成随机数。evaluate和is_valid依赖于ExpressionNode的结构,递归计算或验证表达式。validate_operation是generate_expression的辅助函数,确保生成的表达式合法。canonical_form和format_expression用于表达式的标准化和输出。
2.关键函数流程图
以下是 generate_expression 的流程图:
开始
|
v
生成随机数(概率 0.3 或达到最大操作数) -> 返回叶子节点
|
v
选择随机操作符(+、-、*、/)
|
v
递归生成左子树
|
v
递归生成右子树
|
v
验证操作合法性(validate_operation) -> 如果非法,重新生成
|
v
返回非叶子节点
结束
算法的关键与独到之处
- 递归生成表达式:通过递归随机生成表达式树,确保表达式的多样性和复杂性。
- 规范形式:通过
canonical_form避免生成重复的表达式。 - 合法性验证:在生成过程中实时验证减法和除法的合法性,确保表达式可计算。
3. 项目关键代码与解释
生成表达式
def generate_expression(max_ops, max_num, current_ops=0):
if current_ops > max_ops:
return None
if random.random() < 0.3 or current_ops == max_ops:
return ExpressionNode(value=generate_number(max_num))
op = random.choice(['+', '-', '*', '/'])
left = generate_expression(max_ops, max_num, current_ops + 1)
right = generate_expression(max_ops, max_num, current_ops + 1)
if not validate_operation(left, right, op, max_num):
return generate_expression(max_ops, max_num, current_ops)
return ExpressionNode(left=left, op=op, right=right)
- 功能:递归生成随机表达式树。
- 关键点:
- 通过
random.random()控制生成叶子节点的概率。 - 使用
validate_operation确保操作合法性。
- 通过
计算表达式值
def evaluate(node):
if node.is_leaf():
return node.value.to_fraction()
left = evaluate(node.left)
right = evaluate(node.right)
return {
'+': lambda a, b: a + b,
'-': lambda a, b: a - b,
'*': lambda a, b: a * b,
'/': lambda a, b: a / b
}[node.op](left, right)
- 功能:递归计算表达式树的值。
- 关键点:
- 使用字典映射操作符到对应的计算函数。
- 递归计算左右子树的值。
4. 测试用例
以下是 10 个测试用例及其说明:
| 测试用例 | 预期结果 | 说明 |
|---|---|---|
1 + 2 |
3 |
简单加法 |
3 - 2 |
1 |
简单减法 |
2 * 3 |
6 |
简单乘法 |
6 / 2 |
3 |
简单除法 |
1/2 + 1/2 |
1 |
分数加法 |
1/2 - 1/3 |
1/6 |
分数减法 |
1/2 * 2/3 |
1/3 |
分数乘法 |
1/2 / 1/4 |
2 |
分数除法 |
1 + 2 * 3 |
7 |
运算符优先级 |
(1 + 2) * 3 |
9 |
括号优先级 |
正确性验证
- 通过手工计算验证每个测试用例的预期结果。
- 使用
evaluate函数计算结果并与预期结果对比。
5. 结对项目经验总结
- 鼓励试错:“发现问题比快速推进更有价值”
- 主动表达思路:边写代码边解释意图,如“这里用递归处理树结构,因为层级不确定”。
- 及时提问与反馈:发现问题时直接指出
- 避免长时间沉默:若卡壳,可共同画流程图或伪代码理清逻辑。

浙公网安备 33010602011771号