首页 > 其他分享 >结对项目——四则运算

结对项目——四则运算

时间:2024-09-28 21:25:22浏览次数:7  
标签:结对 temp 项目 四则运算 list questions answer generate append

结对项目——四则运算

这个作业属于哪个课程 软工22级计科12班
这个作业的要求在哪里 作业要求
这个作业的目标 实现四则运算的结对编程

项目成员

姓名 学号 GitHub链接 分工
谭立业 3122004365 github 项目功能的基本实现,博客的编写
罗锴佳 3122001905 github 功能函数的测试与完善,异常处理,bug修复以及性能分析

PSP表格

1.基本功能

实现一个自动生成小学四则运算题目并且可以进行对答案进行检查的程序,可以使用命令行参数控制生成题目的个数,范围等。

2.项目开发

2.1.开发环境:

  • 编程语言:Python

  • 编程环境:Pycharm

2.2.项目结构:

2.3项目整体设计与实现过程:

2.4函数接口设计

函数接口 功能 参数解释
Transform(list) 将列表题目中的分数变成真分数 list:题目列表
generate_random(r) 生成随机数 r:题目的范围
generate_one_bracket(list, f, s) 对于一个题目列表生成一个括号 list:题目列表,f,s: 一个括号插入的位置
generate_two_bracket(list, fir, sec, thi, four) 对于一个题目列表生成两个括号 list:题目列表 fir, sec, thi, four: 两个括号插入的位置
generate_parentheses(operator_count, list) 随机生成括号 list:题目列表 operator_count:运算符的个数
generate_space(list) 将列表转化为算术表达式,并在每一项之间都添加空格 list:题目列表
generate_exercise_answer(r, n) 生成题目和答案文件 r:题目的范围 n:题目的数目
generate_Grade(Exercise_File, Answer_File) 答案检查 Exercise_File:题目文件路径 Answer_File:答案文件路径
main() 主函数 通过命令行输入参数

2.6函数调用关系

2.7主要算法代码及说明

主要算法:generate_exercise_answer(r, n):题目与答案文件的生成

点击查看代码
def generate_exercise_answer(r, n):
    # r为输入的范围,n为题目的个数
    # questions用来存放算术表达式
    continue_time = 0
    questions = []
    questions_F = []
    # 定义列表来存放答案
    answers = []
    # 生成运算式
    operators = ['+', '-', '×', '÷']
    allOperators = ['+', '-', '×', '÷', '(', ')']
    # 通过循环的方式随机生成算数表达式
    while len(answers) < n:
        # 此处的意思为随机产生运算符的个数
        operator_count = random.randint(1, 3)
        # 当为一个运算符的时候
        if operator_count == 1:
            list = []
            # 生成两个随机数和一个随机运算符
            count1 = generate_random(r)
            count2 = generate_random(r)
            operator = random.choice(operators)
            # 存放在列表中
            list.append(count1)
            list.append(operator)
            list.append(count2)
            # 随即生成括号构造算数表达式
            list = generate_parentheses(operator_count, list)
            # 将假分数转换为真分数
            list_temp = Transform(list)
            # 生成算术表达式
            question_F = generate_space(list)
            # 生成真分数表达式
            question_T = generate_space(list_temp)

            temp = question_F.replace('×', '*').replace('÷', '/')
            # 异常处理,若出现除以0的情况,直接跳过后续步骤并开始新一轮的生成
            try:
                answer = Fraction(eval(temp)).limit_denominator()
            except ZeroDivisionError:
                continue
            # 如果答案的结果大于给定的范围,或者为负数,那么该情况不合理,直接跳过后续步骤并开始新一轮的生成
            if answer < 0 or answer > r:
                continue
            # 将答案转换为字符串
            answer_temp = str(answer)
            # 将符合条件的算数表达式以及答案存入questions和answers列表中
            questions.append(question_T)
            questions_F.append(question_F)
            answers.append(answer_temp)

        # 当运算符为两个时
        if operator_count == 2:
            list = []
            count1 = generate_random(r)
            count2 = generate_random(r)
            count3 = generate_random(r)
            operator1 = random.choice(operators)
            operator2 = random.choice(operators)
            list.append(count1)
            list.append(operator1)
            list.append(count2)
            list.append(operator2)
            list.append(count3)
            # 为列表添加括号
            list = generate_parentheses(operator_count, list)
            list_temp = Transform(list)
            # 为原假分数生成算数表达式
            question_F = generate_space(list)
            # 为真分数生成算数表达式
            question_T = generate_space(list_temp)
            temp = question_F.replace('×', '*').replace('÷', '/')
            # 异常处理,若出现除以0的情况,直接跳过后续步骤并开始新一轮的生成
            try:
                answer = Fraction(eval(temp)).limit_denominator()
            except ZeroDivisionError:
                continue
            # 如果答案的结果大于给定的范围,或者为负数,那么该情况不合理,直接跳过后续步骤并开始新一轮的生成
            if answer < 0 or answer > r:
                continue
            answer_temp = str(answer)
            questions.append(question_T)
            questions_F.append(question_F)
            answers.append(answer_temp)
        else:
            list = []
            count1 = generate_random(r)
            count2 = generate_random(r)
            count3 = generate_random(r)
            count4 = generate_random(r)
            operator1 = str(random.choice(operators))
            operator2 = str(random.choice(operators))
            operator3 = str(random.choice(operators))
            list.append(count1)
            list.append(operator1)
            list.append(count2)
            list.append(operator2)
            list.append(count3)
            list.append(operator3)
            list.append(count4)
            # 为列表添加括号
            list = generate_parentheses(operator_count, list)
            # 将假分数转换为真分数
            list_temp = Transform(list)
            # 生成算术表达式
            question_F = generate_space(list)
            # 生成真分数表达式
            question_T = generate_space(list_temp)

            # 异常处理,若出现除以0的情况,直接跳过后续步骤并开始新一轮的生成
            temp = question_F.replace('×', '*').replace('÷', '/')
            try:
                answer = Fraction(eval(temp)).limit_denominator()
            except ZeroDivisionError:
                continue
            # 如果答案的结果大于给定的范围,或者为负数,那么该情况不合理,直接跳过后续步骤并开始新一轮的生成
            if answer < 0 or answer > r or answer.denominator > 10:
                continue
            answer_temp = str(answer)
        # 判断跟新生成的表达式与之前的表达式是否等价。
        # 1.如果生成的answer值和之前answers钟所存的值有相等的
        # 2.同时,新生成的题目通过去括号重新排序后与之前相等的

        question_Switch = False
        answer_Switch = False
        questions_temp = []
        # 对questions的quetsions变成可以比较是否等价的1样子
        for i in range(len(questions_F)):
            questions_temp.append(''.join(sorted(questions_F[i].replace('(', '').replace(')', '').replace(' ', ''))))
        if answer_temp in answers:
            answer_Switch = True
        if ''.join(sorted(question_F.replace('(', '').replace(')', '').replace(' ', ''))) in questions_temp:
            question_Switch = True
        if question_Switch == True and answer_Switch == True:
            continue_time += 1
            continue
            # 防止生成的式子等价太多
        if continue_time >= 10000:
            raise Exception("提供的范围过小")
        questions.append(question_T)
        questions_F.append(question_F)
        answers.append(answer_temp)

    # 将questions 和 answers 写入文件

    questions_New = []
    for i in range(len(questions)):
        data = '四则运算题目' + str(i + 1) + '. ' + questions[i] + '\n'
        questions_New.append(data)

    answers_New = []
    for i in range(len(answers)):
        # 将答案列表中的假分数转换为真分数输出
        temp = Fraction(eval(answers[i])).limit_denominator()
        if temp.denominator != 1 and temp.numerator > temp.denominator:
            ans = '答案' + str(i + 1) + ". " + str(temp.numerator // temp.denominator) + "'" + str(
                temp - temp.numerator // temp.denominator) + '\n'
            answers_New.append(ans)
        else:
            ans = '答案' + str(i + 1) + ". " + str(temp) + '\n'
            answers_New.append(ans)

    # 将列表中得到内容存入到.txt文件中
    fp1 = open('Exercises.txt', 'w')
    fp1.writelines(questions_New)
    fp2 = open('Answers.txt', 'w')
    fp2.writelines(answers_New)
    fp1.close()
    fp2.close()

该函数可以生成n个范围在r内的题目以及这些题目的答案,首先定义三个列表,生成过程中的中间列表,最终记录题目和答案的列表,通过给定的范围,产生符合范围的随机的运算符的个数,进而产生随机数和括号,用pycharm的fraction库的eval()来计算字符串表达式,得出结果,接着对结果进行检查是否合法,最后检查是否有重复的题目,如果上述问题都解决,将这一次产生的题目和结果存入题目文件和答案文件路径中。若其中有一项不符合则直接跳过,以此类推产生n个符合要求的题目和答案。

3.异常测试

3.1命令行输入参数异常:

①输入的命令不是-r -n 或者 -a -e则抛出异常

点击查看代码
else:
    raise Exception(
        '请按以下格式输入:'
        'python Main.py -n [int] -r[int] '
        '或 '
        'python Main.py -e [str] -a [''str]')

测试结果:

②参数输入为负数,抛出异常

点击查看代码
if args.n < 0 or args.r < 0:
    raise Exception('输入的参数为负数,请重新输入')

测试结果:

③提供的文件路径不存在,抛出异常

点击查看代码
if not os.path.exists(Exercise_File):
    raise f'没有找到"{Exercise_File}" 文件'
if not os.path.exists(Answer_File):
    raise f'没有找到"{Answer_File}" 文件'

测试结果:

3.2除零异常:

点击查看代码
try:
   answer = Fraction(eval(temp)).limit_denominator()
except ZeroDivisionError:
    continue

对于除以0的情况,抛出除零异常,该次出题作废,继续下一次出题。

3.3代码覆盖率

利用pycharm自带的coverage进行代码覆盖率的测试如下:

测试报告中显示,覆盖率为70%,Main中还有未被覆盖的代码,需要改进代码

3.4代码改进

在随机生成数字代码中发现,范围的设置有缺陷范围过大,导致最后的答案结果都为零,将生成的结果的分数的分母的范围缩小,防止生成随机数过小结算结果为零。

点击查看代码
up_limit = random.randint(0, r * r)
        down_limit = random.randint(1, r)
        result = Fraction(up_limit, down_limit).limit_denominator()
    else:
        result = random.randint(0, r)
    if result > r:
        return generate_random(r)

4.测试运行

命令行参数给出参数

①生成题目:

②题目文件:

③答案文件:

④答案检查:

⑤生成1万道题目

结果为:

5.性能测试

使用pycharm的Cprofile进行性能测试:

其中:

- ncalls: 函数调用的次数。
- tottime: 函数的总运行时间。
- percall: 平均每次函数调用的运行时间(tottime除以ncalls)。
- cumtime: 函数及其所有子函数调用的总运行时间。
- percall: 平均每次函数调用的累积运行时间(cumtime除以ncalls)。
- filename:lineno(function): 函数所在的文件名、行号以及函数名。

6.项目感受

在参与结对项目的过程中,我们分工明确,深刻体会到了合作的力量与魅力,虽然在本次项目中我们也遇到一些问题与挑战,但是最后还是解决了,这段项目经历不仅提升了我们各自的专业技能,更在团队协作、沟通交流以及问题解决能力上给了我们宝贵的成长。

标签:结对,temp,项目,四则运算,list,questions,answer,generate,append
From: https://www.cnblogs.com/tanliye/p/18437968

相关文章

  • 结对项目
    成员姓名学号李心怡3222004336郑梦瀚3222004340作业这个作业属于哪个课程班级链接这个作业要求在哪里作业链接这个作业的目标二人合作实现一个自动生成小学四则运算题目的命令行程序Github链接:点击此处PSP表格PSP2.1PersonalSoftwar......
  • 结对项目
    这个作业属于哪个课程计科22级12班这个作业要求在哪里作业要求这个作业的目标实现一个自动生成小学四则运算题目的命令行程序姓名&学号:姓名学号董雯霖3122004780陈金星3122004774GitHub链接:https://github.com/1534063091/Arithmometer一......
  • 结对项目
    这个作业属于哪个课程计科2班这个作业要求在哪里作业要求这个作业的目标<要求实现一个自动生成小学四则运算题目的命令行程序>[作业地址](https://github.com/cr1017/3122004813)一、时间预估及实际花费时间PSP表格PSP2.1PersonalSoftwareProcessS......
  • 实现一个自动生成小学四则运算题目的命令行程序
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标通过实现一个自动生成小学四则运算题目的命令行程序提高软件开发能力姓名李佳聪......
  • 结对项目
    这个作业属于哪个课程课程这个作业的要求在哪里结对项目这个作业的目标实现一个自动生成小学四则运算题目的命令行程序一、合作成员项目成员学号github仓库地址黄锐3222004335github王伊若3222004382PSP2.1PersonalSoftwareProcess......
  • 结对项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标组队编程实现四则运算的项目组队成员阿依古再丽(3222004721)、张汉洁(3222004598)这......
  • 结对项目
    姓名学号Github项目地址薛秋昊3122004369https://github.com/0818XR/0818XR/tree/main/3122004369/GenerateArithmeticProblems曾俊涛3122004373一.PSP表格PSP2.1PersonalSoftwareProcessStages预估耗时(分钟实际耗时(分钟)Planning计划1010......
  • 结对项目
    这个作业属于哪个课程 软件工程课程这个作业要求在哪里 结对项目这个作业的目标 按照要求写一个四则运算生成器成员一 罗祖文3122004537成员二 郑志涛312004547GitHub地址:https://github.com/Lzw1322/3122004537PSP2.1PersonalSoftwareProcessStages预估耗时(分钟......
  • 结对项目
    姓名学号陈祥意3122004821肖商3122004837GitHub地址https://github.com/Csneer/auto_generate_formulaPSP表格PSP2.1PersonalSoftwareProcessStages预估耗时(分钟)实际耗时(分钟)Planning计划4050Estimate估计这个任务需要多少时间1460......
  • 结对项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标学习合作编程开发项目,继续熟悉运用性能分析工具和PSP表格管理时间,养成良好编程风格......