这个作业属于哪个课程 | 21计科34班 |
---|---|
这个作业要求在哪里 | 结对项目 |
这个作业的目标 | 自动生成四则运算题目、检查四则运算结果 |
https://github.com/jack1349/jackchen1349/tree/master/3121005204
1、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 20 |
Estimate | 估计这个任务需要多少时间 | 180 | 210 |
Development | 开发 | 150 | 180 |
Analysis | 需求分析 (包括学习新技术) | 60 | 40 |
Design Spec | 生成设计文档 | 60 | 40 |
Design Review | 设计复审 | 40 | 120 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
Design | 具体设计 | 40 | 50 |
Coding | 具体编码 | 60 | 80 |
Code Review | 代码复审 | 30 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 40 | 30 |
Reporting | 报告 | 40 | 30 |
Test Repor | 测试报告 | 40 | 30 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 20 |
合计 | 840 | 920 |
2、 效能分析
程序运行的总时间为0.011s,而在所有函数中运行时间最长的是0.004s,整体的性能还是不错的。
3、 设计实现过程
4、 代码说明
def generate_operand(args):
# 生成一个随机数,包括真分数的分子和分母
if random.random() < 0.5:
operand = random.randint(1, args.range)
else:
operand = Fraction(random.randint(1, args.range), random.randint(1, args.range))
return operand
这个函数主要目的是为了实现式子中整数和分数的生成,通过生成随机数来决定,数的大小默认为10。
def generate_expression(args):
# 生成一个随机数作为第一个操作数
expression = str(generate_operand(args))
# 随机选择运算符数量,最多不超过3个
num_operators = random.randint(1, 3)
for i in range(num_operators):
# 随机选择运算符
operator = random.choice(['+', '-', '*', '/'])
# 生成下一个操作数
operand = generate_operand(args)
if i == 0:
expression = f"{expression} {operator} {operand}"
else:
# 随机决定是否加括号
if random.random() < 0.5:
if i == num_operators - 1 or random.random() < 0.5:
expression = f"({expression}) {operator} {operand}"
else:
expression = f"({expression} {operator} {operand})"
else:
expression = f"{expression} {operator} {operand}"
return expression
运算符和运算符的数量都是随机生成的,当然,括号的添加在随机生成的情况下,需要一定的概率才能添加。生成的数通过字符串的形式拼接。
def generate_question(args, generated_questions):
while True:
# 生成表达式
expression = generate_expression(args)
# 构建题目字符串
question = expression
# 如果题目已经生成过,重新生成
if question not in generated_questions:
generated_questions.add(question) # 将生成的题目添加到集合中,以防重复
break
# 设置默认值
answer = None
try:
# 计算答案
answer = Fraction(eval(expression)).limit_denominator()
if answer < 0:
return generate_question(args, generated_questions)
if answer.numerator > answer.denominator and answer.numerator % answer.denominator != 0:
# 将分数转换为带分数的形式
whole_part, fractional_part = divmod(answer.numerator, answer.denominator)
# 将带分数格式化为字符串
answer = f"{whole_part}'{fractional_part}/{answer.denominator}"
except ZeroDivisionError:
return generate_question(args, generated_questions)
return question, answer
为了不重复添加式子,创建generated_questions集合,将生成的所有式子都添加进集合中,方便判断新生成的式子是否已经存在。
对于计算生成式子的答案,为了使结果表示的更加规范整洁,所有的小数都通过真分数的形式表达。所以需要借助divmod函数计算出式子的整数和余数部分,最后结果也是通过字符串的形式保存。
5、 测试运行
(1)第一个命令行是生成十个式子,且式子中的数字小于10;
第二个命令行是将生成的式子文件和答案文件进行批改,判断答案的对错,将结果保存在Grade.txt文件中
(2)不仅可以判断对错,还可以判断运算表达式是否正确
比如,删除第2个表达式中的一个括号
将会提醒表达式错误。
或者将第一题的分母为0
同样会提醒错误
(3)如果答案文件中的表示不是真分数会不会出问题呢?当然,我们在这里也做出了处理。
我们将最后一题的答案8'1/2改为17/2
可以看到判断结果依旧正确
(4)对于文件不存在的情况我们也有处理
6、 项目小结
结对编程是一种协作方式,一起工作来解决问题或完成项目。这种方式可以带来很多好处,但也需要一些注意事项和经验教训。以下是总结结对编程项目的一些成败得失、经验教训和分享:
成功的方面:
-
知识分享: 结对编程鼓励团队成员分享知识和技能。每个人都有自己的专长,这可以帮助团队共同学习和成长。
-
代码质量: 结对编程通常会导致更高质量的代码,因为两个人一起审查和讨论代码,可以发现潜在的问题并进行改进。
-
问题解决: 在结对编程中,两个人可以一起讨论和解决问题,通常能够更快地找到解决方案。
-
互相监督: 结对编程可以减少错误,因为两个人可以互相监督和校对彼此的工作。
-
设计和架构: 在结对编程中,可以更深入地讨论和设计项目的架构和解决方案,以确保系统的可维护性和可扩展性。
失败和挑战:
-
沟通: 沟通是结对编程的关键。如果合作伙伴之间的沟通不畅,可能会导致问题和误解。
-
角色分工: 在结对编程中,需要明确每个人的角色和任务分工。如果不清晰,可能会导致混乱和重复工作。
-
时间管理: 结对编程可能需要更多的时间,因为两个人需要共同决策和讨论。需要合理安排时间,以确保项目进度。
-
冲突处理: 有时合作伙伴之间可能会有不同意见或冲突。需要建立良好的冲突解决机制,以确保问题得到妥善解决。
经验教训和建议:
-
明确目标和期望: 在开始结对编程项目之前,明确项目的目标和期望,以确保双方都明白任务。
-
定期交流: 保持定期的交流,分享项目进展和反馈。这有助于避免偏离轨道并保持团队的一致性。
-
灵活性: 需要灵活适应不同的工作风格和观点。尊重合作伙伴的意见,共同寻找折中方案。
-
共享学习: 结对编程是一个学习的机会。不仅仅是完成任务,还可以共同学习新的技术和最佳实践。
-
实践: 结对编程需要实践。初始时可能会有挣扎,但随着时间的推移,可以更好地适应合作模式。
-
互相赞赏: 结对编程需要团队合作和互相赞赏。在项目结束后,分享彼此的成功和互相赞扬。
总的来说,在这次合作中,可以提高代码质量,促进知识分享,但也需要良好的沟通和合作。通过合适的计划和团队文化,可以最大程度地利用合作的优势。
标签:结对,编程,题目,四则运算,生成,random,命令行,answer,expression From: https://www.cnblogs.com/jackchen1349/p/17724332.html