实现一个自动生成小学四则运算题目的命令行程序

发布时间 2023-09-23 18:11:11作者: jackchen1349
这个作业属于哪个课程 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、 项目小结

结对编程是一种协作方式,一起工作来解决问题或完成项目。这种方式可以带来很多好处,但也需要一些注意事项和经验教训。以下是总结结对编程项目的一些成败得失、经验教训和分享:

成功的方面:

  1. 知识分享: 结对编程鼓励团队成员分享知识和技能。每个人都有自己的专长,这可以帮助团队共同学习和成长。

  2. 代码质量: 结对编程通常会导致更高质量的代码,因为两个人一起审查和讨论代码,可以发现潜在的问题并进行改进。

  3. 问题解决: 在结对编程中,两个人可以一起讨论和解决问题,通常能够更快地找到解决方案。

  4. 互相监督: 结对编程可以减少错误,因为两个人可以互相监督和校对彼此的工作。

  5. 设计和架构: 在结对编程中,可以更深入地讨论和设计项目的架构和解决方案,以确保系统的可维护性和可扩展性。

失败和挑战:

  1. 沟通: 沟通是结对编程的关键。如果合作伙伴之间的沟通不畅,可能会导致问题和误解。

  2. 角色分工: 在结对编程中,需要明确每个人的角色和任务分工。如果不清晰,可能会导致混乱和重复工作。

  3. 时间管理: 结对编程可能需要更多的时间,因为两个人需要共同决策和讨论。需要合理安排时间,以确保项目进度。

  4. 冲突处理: 有时合作伙伴之间可能会有不同意见或冲突。需要建立良好的冲突解决机制,以确保问题得到妥善解决。

经验教训和建议:

  1. 明确目标和期望: 在开始结对编程项目之前,明确项目的目标和期望,以确保双方都明白任务。

  2. 定期交流: 保持定期的交流,分享项目进展和反馈。这有助于避免偏离轨道并保持团队的一致性。

  3. 灵活性: 需要灵活适应不同的工作风格和观点。尊重合作伙伴的意见,共同寻找折中方案。

  4. 共享学习: 结对编程是一个学习的机会。不仅仅是完成任务,还可以共同学习新的技术和最佳实践。

  5. 实践: 结对编程需要实践。初始时可能会有挣扎,但随着时间的推移,可以更好地适应合作模式。

  6. 互相赞赏: 结对编程需要团队合作和互相赞赏。在项目结束后,分享彼此的成功和互相赞扬。

总的来说,在这次合作中,可以提高代码质量,促进知识分享,但也需要良好的沟通和合作。通过合适的计划和团队文化,可以最大程度地利用合作的优势。