结对项目——四则运算

news/2024/9/28 21:24:04/文章来源:https://www.cnblogs.com/tanliye/p/18437968

结对项目——四则运算

这个作业属于哪个课程 软工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 = 0questions = []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:continueanswer_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:continueanswer_temp = str(answer)# 判断跟新生成的表达式与之前的表达式是否等价。# 1.如果生成的answer值和之前answers钟所存的值有相等的# 2.同时,新生成的题目通过去括号重新排序后与之前相等的question_Switch = Falseanswer_Switch = Falsequestions_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 = Trueif ''.join(sorted(question_F.replace('(', '').replace(')', '').replace(' ', ''))) in questions_temp:question_Switch = Trueif question_Switch == True and answer_Switch == True:continue_time += 1continue# 防止生成的式子等价太多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.项目感受

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/805393.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

引用拷贝,浅拷贝,深拷贝

参考资料 水平有限,欢迎交流! kimi 【【每天一个技术点】引用拷贝、浅拷贝、深拷贝】 一文搞懂Java引用拷贝、浅拷贝、深拷贝 - bigsai - 博客园 (cnblogs.com) 【黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难】 1. 引用拷贝 (起绰号) 引用拷贝并不是真正意义上…

黑马PM-内容管理-运营管理

消息推送账号管理权限管理日志管理

Blender快速入门教程1简介

0 简介Blender是最著名的 3D 计算机图形制作免费程序之一。有了 Blender,你可以创建角色、道具、环境以及你的想象力所能产生的几乎所有其他东西。它不仅可以创建对象。你还可以让它们运动起来。在动画中讲述一个故事,带领人们穿越你自己创造的世界,或者为一些视频片段添加特…

今天我有博客了!

今天我有博客了!我要把我的编程心得写下来。 今天,我先写了蜗牛打怪兽。我发现需要打的次数都是2^(n)-1,于是我用while循环求出是2的几次方,再用变量一直乘2,最后-1。以下是具体示例。接着,我写了POW。这题限制比较紧,所以不能直接算,得看c是奇数还是偶数:偶数比绝对值…

『模拟赛』csp-s模拟赛6

『模拟赛』csp-s模拟赛6『模拟赛』csp-s模拟赛6 挂分日寄:0+20+0+0 喵喵赛时对拍拍了10000个点都没拍出来,赛后一下就拍出错来了,我谔谔。 T1 DP喵~ 首先 sort 一遍方便处理 其实转移时加一个 abs 取绝对值就可,纯纯多此一举 设 \(f[i,j,1/0]\) 为前 \(i\) 个数中选 \(j\) …

树莓派pico rp2040 使用rust 在ssd1306上显示中文信息

使用u8g2-font + embedded-graphics ,在rp2040 pico上用 ssd1306输出中文信息在rp2040上用DHT22 + ssd1306显示温度信息,用 embedded-graphics库和ssd1306库来实现。但实现的效果不是很理想,无法在ssd1306屏幕上显示中文。为了解决这个问题,在github和crates.io上面找了几天…

typeScript 的第一步---安装

Node.js/浏览器,只认识JS代码,不认识TS代码,需要将TS代码转化为JS代码,然后才能运行。 安装命令:npm i -g typescript 或者 yarn global add typescript 注意:Mac电脑安装全局包时,需要通知添加sudo获取权限。sudo npm i -g typescript 验证安装是否成功:tsc -v 查…

为什么用 AWS CLI?因为我懒得点鼠标!

在这篇博客中,我们一起深入探索 AWS CLI 的世界,从零开始,逐步构建在云端的家园。将介绍 AWS CLI 的基本功能和使用场景,如何创建 IAM 用户、VPC、子网、安全组、EC2 实例等,甚至还会搭建一个应用负载均衡器(ALB)。无论你是初学者还是有一定基础的用户,都能通过本指南掌…

妙用编辑器:使用Notepad--正则表达式从命令结果报文快速生成新命令

应用场景 日常生活中有些维护场景,比如检查设备状态,执行查询命令后,得到精简结果报文,如果要更深入的检查状态,可能还要执行其他命令,逐个对象进行查询,这里涉及到快速从报文生成查询指令的功能。 比如有如下一个从LST 命令查询出来的报文,需要快速的生成DSP命令,逐个…

bs4解析并提取人民网新闻标题数据

1. 目标url:http://www.people.com.cn/ 2. 查找标题信息所在标签:标题的文本信息在<a>标签中,且<a>标签有target属性,属性值为"_blank"。<a>标签有父辈标签<div>和<h3>。 当需要根据元素的层级关系、属性组合等复杂条件定位时;文…

volatile关键字最全原理剖析

介绍 volatile是轻量级的同步机制,volatile可以用来解决可见性和有序性问题,但不保证原子性。 volatile的作用:保证了不同线程对共享变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。 禁止进行指令重排序。底层原理 内存屏障 vol…

2024.9.28 代码源模拟赛

省流:45+20+5+0=70省流:\(45+20+5+0=70\) 简称:唐诗在此膜拜 \(klz\) \(Heldivis\) \(Sorato\) \(czl\) \(Ech0\_7\) yxans lihe_qwq 大佬 T1 先看的 T1 ,想了一个拓排(其实是看错题了),然后过了第一个样例,然后咋调都过不去,就去码暴力了。 过了大概 10min 发现看错题…