结对项目
这个作业属于哪个课程 | 22级计科12班 |
---|---|
这个作业要求在哪里 | 作业要求 |
这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
姓名 | 学号 |
---|---|
陈祥意 | 3122004821 |
肖商 | 3122004837 |
GitHub地址 |
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 40 | 50 |
Estimate | 估计这个任务需要多少时间 | 1460 | 1290 |
Development | 开发 | 600 | 540 |
Analysis | 需求分析 (包括学习新技术) | 40 | 35 |
Design Spec | 生成设计文档 | 60 | 60 |
Design Review | 设计复审 (和同事审核设计文档) | 50 | 45 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范 | 30 | 20 |
Design | 具体设计 | 80 | 70 |
Coding | 具体编码 | 200 | 160 |
Code Review | 代码复审 | 80 | 60 |
Test | 测试(自我测试,修改代码,提交修改) | 100 | 80 |
Reporting | 报告 | 60 | 60 |
Test Report | 测试报告 | 60 | 40 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 | 40 | 50 |
合计 | 1460 | 1290 |
3.性能分析
可知,生成计算式时,耗时最多的函数为:generate_problems_and_answers(n,r)
可知,在对比两文件答案时,耗时最多的函数为:compile(pattern, flags=0)
4.设计实现过程
5.代码说明
生成表达式关键代码
点击查看代码
def generate_problem(r):
# 确保不产生负数和符合真分数要求
operators = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv
}
# 随机生成运算符个数(1到3个)
num_operators = random.randint(1, 3)
terms = []
for _ in range(num_operators + 1): # 生成操作数
if random.choice([True, False]): # 50%概率选择自然数
term = random.randint(1, r)
else: # 50%概率选择分数
numerator = random.randint(1, r)
denominator = random.randint(1, r) + 1 # 确保分母不为0
term = Fraction(numerator, denominator)
terms.append(term)
# 随机选择运算符
expression = str(terms[0])
for i in range(num_operators):
op = random.choice(list(operators.keys()))
expression += f" {op} {terms[i + 1]}"
# 计算结果
try:
result = problem_eval(expression)
except ZeroDivisionError:
return generate_problem(r) # 重新生成题目以避免除以零
# 检查结果
if result < 0 or (result.denominator != 1 and result.numerator < 0):
return generate_problem(r) # 重新生成题目以避免负数
# 格式化结果为真分数形式
formatted_result = format_fraction(result)
expression = expression.replace('*', '×')
if re.search(r'\s/\s', expression):
expression = re.sub(r'\s/\s', ' ÷ ', expression)
return expression, formatted_result
判断答案关键代码
点击查看代码
def calculate_answer(exercise):
exercise = exercise.strip().split('. ')[1] # 移除题号
# 匹配分数或整数
elements = re.findall(r'\d+/\d+|\d+', exercise) # 匹配分数或整数
operators = re.findall(r'\s[+\-*/]\s', exercise) # 匹配运算符
# 将匹配的数字或分数转换为 Fraction 对象
fractions = [Fraction(e) for e in elements]
# 使用两个栈来处理运算符优先级
values = []
ops = []
for i in range(len(fractions)):
values.append(fractions[i])
if i < len(operators):
op = operators[i].strip()
while ops and precedence(op) <= precedence(ops[-1]):
# if len(values) < 2: # 确保有足够的值进行运算
# break
right = values.pop()
left = values.pop()
operator = ops.pop()
values.append(apply_operator(left, right, operator))
ops.append(op)
# 处理剩余的运算符
while ops:
right = values.pop()
left = values.pop()
operator = ops.pop()
values.append(apply_operator(left, right, operator))
return values[0] # 返回格式化后的结果
6.测试运行
- 随机生成Exercises.txt和Answer.txt
- 随机更改Answer.txt中的答案
- 运行python main.py -e Exercises.txt -a Answers.txt
- 查看Grade.txt的结果可以简单验证程序正确
项目小结
通过两人合作,分工完成一个小项目,可以体验多人合作,完成任务的乐趣。
两人各有所长,所幸都很好地发挥了自己的长处,使得这个结对项目顺利完成。