一、需求

1.使用-n 参数控制生成题目的个数

2.使用-r 参数控制题目中数值(自然数、真分数和真分数分母)的范围

3.生成的题目中计算过程不能产生负数

4. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。

5. 每道题目中出现的运算符个数不超过3个。

6. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。

7.生成的题目存入执行程序的当前目录下的Exercises.txt文件

8.在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件

9. 程序应能支持一万道题目的生成。

10. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:

Myapp.exe -e .txt -a .txt

统计结果输出到文件Grade.txt,格式如下:

Correct: 5 (1, 3, 5, 7, 9)

Wrong: 5 (2, 4, 6, 8, 10)

二、PSP2.1表格

PSP:

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)

Planning

计划

20

30

· Estimate

· 估计这个任务需要多少时间

20

30

Development

开发

1230

1665

· Analysis

· 需求分析 (包括学习新技术)

120

300

· Design Spec

· 生成设计文档

60

60

· Design Review

· 设计复审 (和同事审核设计文档)

30

50

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

10

5

· Design

· 具体设计

30

40

· Coding

· 具体编码

900

1100

· Code Review

· 代码复审

40

30

· Test

· 测试(自我测试,修改代码,提交修改)

40

80

Reporting

报告

50

70

· Test Report

· 测试报告

10

10

· Size Measurement

· 计算工作量

10

20

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

30

40

合计

1300

1765

三、设计实现过程:

1.功能1~9的实现步骤

· 一开始题目运行采用递归的方法,后来调用的函数过多,递归函数太复杂,于是改成for生成题目

· 查重用了字典的方法

· 随机括号的生成费时良久,考虑到随机的各种情况,左括号和右括号的定位问题,存储结构等等问题。

· 在寻找计算的简便方法的时候,我们找到一个函数eval(string)可以直接识别并计算一整条string。

· 减号的判断,由于计算的方法不是根据括号从内到外计算的,要一个个计算却会使得函数过于复杂,向同学取经后,我们还是采用了负数舍去的方法。

2.功能10的实现过程:

· 用正则表达式检查输入的文本格式是否正确

· 根据空格split分别存储真分数等各个数值

· 调用两个函数进行,分数与真分数互相转换

效能分析:

CPU运行时间:

10000道题的生成时间:

100道题的时间:

功能10:

可以看出来到了大量题目的时候,由于查重,时间复杂度成指数级上升。

代码说明:

功能1~9:

1.  #随机生成一道题目中的符号和数字

defrandom_list(self):

char_list = ["+", "-", u"×", u"÷"]

num_list =[]

char_choice =[]

cc = ""loop_times = random.randint(2,4)

for i inrange(loop_times):

static = random.randint(1, self.num_range)

if self.num_range > 1:

float_n =produce_random.choose_num(self)

choice =random.choice([static, float_n])

else:

choice =static

cc +=str(choice)

num_list.append(choice)

if i < (loop_times - 1):

cha =random.choice(char_list)

char_choice.append(cha)

cc +=cha

jo = str(num_list+char_choice)

if jo indic_t.keys():

self.random_list()

else:

dic_t[jo] =0

return char_choice, num_list

2.  #随机生成分数

defchoose_num(self):while(1):

a= random.randint(1, self.num_range**2)

b= random.randint(2, self.num_range)if Decimal(a/b)

3.  #根据符号随机加括号

defplus_(self,char_choice, num_list):

numble= len(num_list) +len(char_choice)

ccc= [""] *numbleif len(char_choice) == 1:pass

else:"""括号对数"""n_kuo= random.randint(0, len(char_choice) - 1)if n_kuo !=0:

p_kuo_l=[]"""设置list1初值"""list1=[]for i inrange(0, len(char_choice)):

z= 2 *i"""改为append"""list1.append(z)

p_kuo_l= random.sample(list1, 1) #按照char的数量来存,2个就是[0,2],3个[0,2,4]

ccc.insert(p_kuo_l[0], '(') #插入1st左边的括号

if len(char_choice) == 2:

ccc.insert(p_kuo_l[i-1] + 4, ')')if len(char_choice) == 3:"""第一个右括号"""

if p_kuo_l[0] ==0:

list1= [4]if p_kuo_l[0] == 2:

list1= [p_kuo_l[0] + int(random.sample([4, 6], 1)[0])]if p_kuo_l[0] == 4:

list1= [8]

p_kuo_r=list1[:]

ccc.insert(p_kuo_r[0],')')

x= p_kuo_l +p_kuo_rif n_kuo == 2: #加第二个右括号

if x[0] == 2:if x[1]==x[0]+4:

y= random.sample([0, x[0]], 1)

ccc.insert(y[0],'(')if y[0] ==0:

ccc.insert(x[1]+1, ')')else:

ccc.insert(x[0]+ 8, ')')else:

y= random.sample([x[0], x[0] + 3], 1)

ccc.insert(y[0],'(')if y[0] == 2:

ccc.insert(x[0]+ 5, ')')else:

ccc.insert(x[0]+ 7, ')')if x[0] ==0:

y=x[0]

ccc.insert(y,'(')

ccc.insert(x[0]+ 8, ')')if x[0] == 4:

y= x[0]-2ccc.insert(y,'(')

ccc.insert(x[0]+7, ')')

num=0

cha=0

list_all= [] #装数字+字符

j =0

flag=True#标记乘号的个数

multi_n =[]#标记除号的个数

divide_n =[]for i inrange(0, len(num_list)):if j == (len(num_list) - 1):

j-= 1flag=False

list_all.append(num_list[i])if i == j and flag ==True:

list_all.append(char_choice[j])

j+= 1j=0for i inrange(0, len(ccc)):if ccc[i] != '':continue

if list_all[j]=='×':

multi_n.append(i)if list_all[j]=='÷':

divide_n.append(i)

ccc[i]=list_all[j]

j+= 1

return ccc, multi_n, divide_n

4. #符号转换,把list改为str来计算,分数周围有自己的括号(计算的时候将分数看成除法来计算)

defjoin_c(self, ccc, multi_n, divide_n):

list1=ccc[:]

ll=[]for i inmulti_n:

list1[i]= '*'

for j individe_n:

list1[j]= '/'

for i inlist1:if type(i) ==Fraction:if i.denominator == 1:

ll.append(str(i))else:

ll.append('('+str(i)+')')elif type(i) ==int:

ll.append(str(i))else:

ll.append(i)

final= ''.join(ll)return final

5.   #计算

defcalculate(final):

result=eval(final)return result

6. #查找小数循环,小数转分数

def ff_c(self, demical): #参数为小数

for i in range(1, 16):

cpart=demical[:i]if len(cpart) < 4:if (cpart * i * 4) == demical[:4 * i]: #4次重复

return cpart #循环体

return 0 #找不到循环体,返回0

#小数转分数

def demical_to_fraction(self, digi, back_num=0):

digi=str(digi)if len(digi) <= 15: #有限小数

returnFraction(digi)

real_num, dot_area= digi.split('.')

float_num=float(digi)for i inrange(len(digi)):

cycle_start=dot_area[i:]

result=self.ff_c(cycle_start)

length= len(str(result)) #循环体的长度

if result: #存在循环体

if i != 0: #不是小数点后第一位

new_number = float_num * (10 ** i) #移位数

self.demical_to_fraction(new_number, i) #递归

break

else: #小数点后的第一位

fraction = Fraction(int(result), int('9' * length)) #小数转分数

final_num = int(real_num) +fractionreturn final_num / (10 ** back_num) #回退移的位数

return False

7.  #最后转为真分数输出

defchange_l(self,li):

hh=[]for i inli:if type(i) ==Fraction:

hh.append(change_ff(i))

hh.append(' ')continue

else:

hh.append(str(i))

hh.append(' ')return hh

8. # 写入文件

defwrite(self, f_line):

self.glocount+= 1count= int((self.glocount + 1) / 2)

tihao= str(count) + '.'file= open('Exercise.txt', 'a')

f_line= tihao + f_line + '='file.write(f_line+ '\n')

file.close()defwrite_a(self, f_line):

self.glocount+= 1tihao= str(int(self.glocount / 2)) + '.'file= open('Answers.txt', 'a')

f_line= tihao +f_line

file.write(f_line+ '\n')

file.close()

功能10:

1. # 支持读取给定的文件

defread_f(name):

with open(name) as Re:

file=Re.readlines()return file

2. #检查文件名是否符合格式

defcheck_file(file_name):if re.match(r"[a-zA-Z0-9]*\..", file_name):returnTrueprint("The file name is not right.")return False

3. #转换分数AND真分数

defchange_re_fra(expre):if re.search("[1-9]\'[1-9]/[1-9]", expre):

l1= expre.split("\'")

l2= l1[1].split("/")

num_1=eval(l1[0])

num_2=eval(l2[0])

num_3= eval(l2[1])

middle_p= num_3*num_1

num_2+=middle_preturnstr(Fraction(num_2,num_3))if expre == '×':

expre= '*'

if expre == '÷':

expre= '/'

returnexpredefchange_ff(fra):

d=fra.denominator

n=fra.numerator

midde= n //dif midde ==0:returnstr(n)

cha= n - d *middeif cha ==0:returnstr(midde)return str(midde)+'\''+str(Fraction(cha,d))

4. #比对提交的和user答案一致性

defbidui(ans,user):

corr,wrong=[],[]

a_line=read_f(ans)

user_line=read_f(user)for i inrange(0,len(a_line)):if a_line[i] ==user_line[i]:

corr.append(str(i))

corr.append(',')else:

wrong.append(str(i))

wrong.append(',')

u1= ''.join(corr)

u2= ''.join(wrong)

co= 'Correct:'+str(len(corr)//2)+'('+u1+')'w= 'Wrong:'+str(len(wrong)//2)+'('+u2+')'write_Grade(co,w,'Grade.txt')

defcompare(file_list):

file=read_f(file_list[0])

gloc=0for i infile:

i=i.rstrip()

lii= i.split('.')

c= lii[1].split(' ')

strr= ''

for j inc:if j != '=':

str=change_re_fra(j)

strr+=str

result=calculate(strr)

f_result=demical_to_fraction(result)

ff_result=change_ff(f_result)

write1(ff_result,'answer2.txt',gloc)

gloc+= 1bidui('answer2.txt',file_list[1])

5.  #写入文件

defwrite1(result, name,glocount):

glocount+= 1count=glocount

tihao= str(count) + '.'file= open(name, 'a')

f_line= tihao +result

file.write(f_line+ '\n')

file.close()defwrite_Grade(c,w,name):

file= open(name, 'a')

file.write(c+'\n'+w)

file.close()

main函数:

if __name__ == '__main__':

file= open('Exercise.txt', 'r+')

file.truncate()

file.close()

file= open('Answers.txt', 'r+')

file.truncate()

file.close()

sys.setrecursionlimit(10000)

dic_t={}if len(sys.argv)>2:

num_range, ti_num=menu()if num_range > 0 and ti_num >0:

instance=produce_random(num_range, ti_num)

instance.running()else:print("输入命令不足")

defmenu():

flag=0

compare_arg=0

file_rrlist=[]for i inrange(len(sys.argv)):if sys.argv[i]=='-e':if check_file(sys.argv[i+1]):

file_rrlist.append(sys.argv[i+1])

compare_arg+= 1

continue

elif sys.argv[i]=='-a':if check_file(sys.argv[i+1]) and compare_arg==1:

file_rrlist.append(sys.argv[i+1])

compare(file_rrlist)

flag= -1

elif sys.argv[i]=='-n' and compare_arg==0:

ti_num= input("请输入题目数量:")

ti_num=int(ti_num)if ti_num<=0:print("数量过少,请重试")breakflag+= 1

elif sys.argv[i]=='-r' and compare_arg==0:

num_range= input("请输入数值范围:")

num_range=int(num_range)if num_range<=1:print("数值范围不存在")continue

else:breakflag+=1

if flag == 1:returnnum_range, ti_numelif flag==-1:return -1,-1

else:print("输入不正确")return 0, 0

defrunning(self):#利用for循环输出多道题

for i inrange(self.num):whileTrue:

char_choice, num_list=self.random_list()

k, multi_n, divide_n=self.plus_(char_choice, num_list)

new_title=self.join_c(k, multi_n, divide_n)

z=calculate(new_title)if z <0:continuefinal_result=demical_to_fraction(z)if type(final_result) == float or final_result==False:continue

if final_result.denominator >self.num_range:continue

else:breaknn_tt=self.change_l(k)

final_result=change_ff(final_result)

nn_tt= ''.join(nn_tt)print(nn_tt)

self.write(nn_tt)

self.write_a(str(final_result))

测试结果分析:

生成题目:

10000道题,范围为1000:

测试文件查错:

总结:

我们采取的分工合作是蔡同学先负责写随机数、menu等等,杜同学写加括号、功能10的实现,之后由于加括号出现了很多bug,两人都在这个函数上掉了大把的头发,前期代码在后期测试时很多地方的需要上有较多的调整,对于有些功能比如查重用了比较暴力的删除法,增加了不少运行时间。

——蔡晓晴:我觉得这次结对编程还是获益良多的,例如我们开始没找到合适的方法来沟通、设计,到后面逐步完善我们的设计方案,修改bug。我觉得这其中彼此的思想碰撞有很大的作用,也谢谢同伴的帮助!(^-^)V

——杜婷萱: 一开始我们采取两个人一边写一边看的形式让我略感压力的同时,双人互挑bug的讨论比一个人的思路更广阔,纸上谈兵也能发现很多的问题,我学习到思路理清楚很重要,如果仅仅只是有个想法而不做深入思考就写代码就会写的很乱,不仅浪费时间,还会难以让同伴理解。而且双方的沟通很重要,两人最好尽量同步,现实代码总比理想的冗余了许多,结对其实更考验写代码的速度和质量。作为一个messy coder蔡同学帮助了我非常多,感谢ヽ( ̄▽ ̄)و

python中四则运算符号_Python-四则运算-蔡晓晴,杜婷萱相关推荐

  1. python中并集符号_python中列表之间求差集、交集、并集

    求两个列表的交集.并集.差集 def diff(listA, listB): # 求交集的两种方式 retA = [i for i in listA if i in listB] retB = lis ...

  2. python中续行符号_Python 的续行标志是( )_大学英语(2)答案_学小易找答案

    [其它]编写C程序,设计学生类型,使用结构体数组实现任务二中的所有功能,即能输入任意多个人的多门课的考试成绩;能计算每个人的总成绩和平均成绩;能输出总分第一名和最后一名的分值;能查询个人成绩信息(包括 ...

  3. python中的@符号的作用

    python中的@符号的作用_weixin_34014555的博客-CSDN博客 Python中的" @"(@)符号有什么作用?_p15097962069的博客-CSDN博客

  4. python中特殊符号怎么输入_python中怎么输入引号

    Python中的引号可分为单引号.双引号和三引号. 在Python中我们都知道单引号和双引号都可以用来表示一个字符串,比如str1 = 'python' str2 = "python&quo ...

  5. python特殊含义符号_python 正则表达式中的特殊符号介绍

    python 2.7.3 正则表达式:正则表达式就是根据自己的需要定义字符串而已, 定义方法: s = r'\d{3,4}' 为了与字符串赋值做区分,定义时需要加个 r . 用途 : 定义好以后可以从 ...

  6. python中的乘方_python乘方运算

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 算数运算符是完成基本的算术运算使用的符号,用来处理四则运算运算符描述实例+加10 ...

  7. python中的乘方_python中的乘方

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 一,算术运算python中的乘方运算符号为 **,比较特殊. 作为运算符,%表示 ...

  8. python中幂运算_python里幂运算

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! "**"运算这个"**"比较简单,就是标 ...

  9. python中幂运算_python的幂运算

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! "**"运算这个"**"比较简单,就是标 ...

最新文章

  1. [扫盲] Salesforce.com: 业界云计算(Cloud Computing)的主要倡导者之一
  2. NOIP2011 提高组 Day1
  3. scanf family API 高级用法
  4. CVPR 2020 HAN:《Hypergraph Attention Networks for Multimodal Learning》论文笔记
  5. HarmonyOS之AI能力·助手类意图识别
  6. GLTF格式——关系描述
  7. kerberos的系统搭建
  8. 本地环境测试二级域名
  9. Docker修改MySQL默认端口
  10. linux安装vsftpd并配置文件,Linux 系统下 vsftpd 的安装与配置
  11. 吾爱破解“凉”了之后,还能去哪儿下载软件?
  12. python 文件夹_使用python进行文件夹对比
  13. 7-24 约分最简分式 (15 分)
  14. Jquery获取单选框与复选框选中的值
  15. 科技金融企业助力乡村振兴,能有多大新意?
  16. Particle for alexa smart home skill (3)
  17. Flutter Win桌面应用环境配置
  18. 迅播Gvod清理缓存与改变缓存文件夹位置的方法
  19. Opera 使用迅雷下载
  20. c# winform中获取当前日期和时间

热门文章

  1. 键盘输入身份证号,输出组成信息
  2. 人力资源知识大全(可以做全盘)
  3. 为什么说摩托罗拉edge双新机是不妥协的诚意之作
  4. Libreoffice安装配置,office文件转PDF
  5. 世嘉MD游戏开发进阶篇【三】:向量归一化的实现及应用
  6. Jingsong Zhang
  7. Linux管道命令符使用
  8. Linux系统故障修复和修复技巧
  9. js传递event参数
  10. IPC设备产生呼吸效应