结对项目
一. github:https://github.com/zjh1234562/exercise_2
二 . PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 1200 | 1270 |
Analysis | 需求分析 | 20 | 30 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 30 | 40 |
Coding Standard | 代码规范 | 40 | 50 |
Design | 具体设计 | 40 | 60 |
Coding | 具体编码 | 960 | 1000 |
Code Review | 代码复审 | 30 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 30 | 30 |
Reporting | 报告 | 200 | 220 |
Test Report | 测试报告 | 12 | 120 |
Size Measurement | 计算工作量 | 30 | 40 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 50 | 60 |
Total | 总计 | 1430 | 1520 |
三. 效能分析:
最开始时的策略是,对于每一个生成的算式,验证通过之后就存放到文件中(当时觉得要节省一下程序运行占用的内存),然后测试生成10000道题目,需要的时间是3.5s。后来觉得这速度可能有点慢,所以变成将每个符合要求的算式存在一个列表里面,最后生成指定数目的题目后再打开文件写入,生成10000道题目需要的时间为1.5s不到。速度提升了,因为文件的io操作所需要的时间一般都比较大,减少文件io速度就会提升。
四. 设计实现过程
本次项目总共有6个类:分别为Calculation(计算类),Main(主类),write(文件操作类),verification(验证类),New_Arithmetic(表达式生成类),Number_generation(数字生成类)。
1.Calculation(计算类):封装了两个方法,分别实现中缀表达式转后缀表达式,后缀表达式计算结果,对于给定的算式,返回一个数值结果。
2.Main(主类):完成参数的提取,调用相应的函数
3.write(文件操作类):文件的读写操作均在该类中
4.verification(验证类):完成的是需求9的功能,因为要从文件中读取题目,读取才来的是字符串,要转换成统一的格式才能去计算结果,如1+1=,读取出来的是"1+1=",需要转成[’1‘,’+‘,’1‘]这样的格式,然后与标准答案比较,记录正确,错误的题号。
5.New_Arithmetic(表达式生成类):该类实现算术表达式的生成,实现去重,不产生负数,添加括号等功能。
6.Number_generation(数字生成类):该类主要提供随机生成数字的功能(包括整数,真分数,带分数)。
五.代码说明
def New_arithmetic(self): #表达式生成主要函数 strlists,intlists,answers=[],[],[]#用来存储生成的表达式以及答案 sum=0 while sum<self.n:#循环生成指定数目的题目 #for j in range(self.n): operator=self.operator() operator_length=len(operator) num_length=operator_length+1 strlist=[] intlist=[] for i in range(num_length+operator_length): num_str,num_int=self.number_generation.str_num() if i%2==0:#偶数位置放操作数 strlist.append(num_str) intlist.append(num_int) else:#奇数位放运算符 op=operator.pop() strlist.append(op) intlist.append(op) self.chufa(strlist,intlist) #self.change(strlist,intlist) if operator_length>1: #操作符大于一个时才需要添加括号 self.kuohao(strlist,intlist,operator_length) #print(strlist) try: answer=self.calculation.calculation(intlist) if answer >= 0:#避免答案为负数的情况 strlists.append(strlist) # intlists.append(intlist) answers.append(answer) if self.isrepeat(answer, answers, strlists) != True: # 如果不重复 sum = sum + 1 else: strlists.pop() # intlists.pop() answers.pop() else: pass except: pass self.write.write('Exercises.txt', strlists) self.write.writeanswer(answers)
def calculation(self,intlist): #后缀表达式结算,比较容易理解,主要利用栈就行了 stack=[] result=self.bolan(intlist) #print(result) for j in result: if type(j) is float: stack.append(j) else: if j=='+': num1=stack.pop() num2=stack.pop() stack.append(num1+num2) elif j=='x': num1=stack.pop() num2=stack.pop() stack.append(num1*num2) elif j == '-': num1 = stack.pop() num2 = stack.pop() stack.append(num2-num1) elif j == '÷': num1 = stack.pop() num2 = stack.pop() stack.append( num2/num1) return stack[0]
def bolan(self,intlist): #中缀表达式转后缀表达式 stack=[] result=[] #intlist=['(',1.0,'+',2.0,')','x',3.0,'÷',4.0] #intlists=[1.0 ,'+', 2.0, 'x', 3.0 ,'+', '(',4.0, 'x', 5.0 ,'+', 6.0,')','x',7.0] for i in intlist: if type(i) is float: result.append(i) else: if stack==[]: stack.append(i) else: if i=='(':#括号特殊一点 stack.append(i) elif i==')': while len(stack)>0: op=stack.pop() if op=='(': break else: result.append(op) else: if self.operation_dict.get(stack[-1]) < self.operation_dict.get(i): stack.append(i) else: while len(stack)>0: if self.operation_dict.get(stack[-1]) >=self.operation_dict.get(i) and stack[-1]!='(': op = stack.pop() result.append(op) else: break stack.append(i) #print(self.result,self.stack) res=result+stack[::-1] return res
def gettopicanswer(self,topicname): #读取文件题目,并转成可以计算的格式 topiclist=[] with open(topicname, 'r')as f: for i in f.readlines(): str=i.replace("\n", "").replace("=", "") res=re.split(r'([()÷x+-])',str)#字符串转成列表形式,如‘1+1’->['1','+','1'],用正则表达式才能满足要求 while '' in res: res.remove('') for i in range(len(res)): if res[i] not in '()÷x+-': str=res[i] num=self.str_to_int(str)#将字符转成数字,因为是自定义的数字形式,处理的时候要特别处理 res[i]=num temp=self.calcultation.calculation(res) topiclist.append(round(temp,3)) return topiclist
六.运行测试
1.-h参看帮助
2. 测试-r , -n:生成10000道题目
Exercises.txt
Answers.txt
3.验证答案
七.项目小结
本次项目总体来说有难度的,主要体现在如何添加括号(添加的括号要符合),如何计算结果。第一个问题的解决比较难,上网查找资料介绍是用二叉树来解决,但是那时我已经写了大部分程序了(用的是列表来存储的),重写程序是不可能了,因此就依靠这样一个方法,首先生成式子的时候不添加括号(这样就会有一个规律,数字的部分在列表的偶数位置,算术符在技术位置),然后就依靠这个规律来添加括号,添加括号的时候还要判断一些无意义的括号,例如加在最外层。第二个问题就比较好解决了,主要了解中缀表达式和后缀表达式,按照原理写出算法就行了。
本次结对项目,本来认为写代码一个人就行了,后来发现,结对有时也能提升速度,而且两个人分析总比一个人要好,考虑的东西也多,全面。总而言之本次结对体验还是
不错的。
结对队友:卓家鸿,颜树钦