1.项目地址
2.PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
120 |
145 |
Estimate |
估计这个任务需要多少时间 |
30 |
30 |
Development |
开发 |
250 |
310 |
Analysis |
需求分析(包括学习新技术) |
200 |
300 |
Design Spec |
生成设计文档 |
120 |
100 |
Design Review |
设计复审 (和同事审核设计文档) |
120 |
200 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
30 |
45 |
Design |
具体设计 |
60 |
90 |
Coding |
具体编码 |
600 |
700 |
Code Review |
代码复审 |
60 |
85 |
Test |
测试(自我测试,修改代码,提交修改) |
60 |
60 |
Reporting |
报告 |
180 |
180 |
Test Report |
测试报告 |
120 |
130 |
Size Measurement |
计算工作量 |
60 |
75 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
120 |
130 |
合计 |
|
2130 |
2580 |
3.效能分析
程序性能分析图:
可以看出调用最多的为与字符串相关的函数
4.程序设计与实现
函数流程
本程序由以下几个函数组成:
(1)命令行控制模块:get_Parameter()
实现代码:
def get_Parameter():#命令行控制模块
parser = argparse.ArgumentParser()
parser.add_argument('-n', help='设定题目数量',type=int)
parser.add_argument('-r', help='设定数值范围',type=int)
return parser.parse_args()
(2)获取随机数字和运算符号:get_Arithmetic()
实现代码:
def get_Arithmeticl(self):#获得随机数字与符号
symbol=[]
numerical=[]
syb=0
n=1
m=0
i=random.randint(1, 3)
for x in range(i):
sy=random.choice(['+','-','×','÷'])
if sy=='+'or sy=='-':
syb +=10**(i-x-1)
else :
syb += 2 * (10 ** (i - x - 1))
symbol.append(sy)
if self.r < 10:
n = int(10 / self.r)
if n==1:
while m <= i:
numerical.append(Fraction(random.randint(1, self.r), random.randint(1, self.r)))
m+=1
else:
while m <= i:
nu = Fraction(random.randint(1, self.r * n), random.randint(1, self.r * n))
if nu<=self.r:
numerical.append(nu)
m += 1
return symbol,syb,numerical,i
(4)四则运算:get_Calculate()
实现代码:
def get_Calculate(a,b,c):#四则运算
if c=='+':
results=a+b
elif c=='-':
results=a-b
elif c=='×':
results=a*b
else:results=a/b
return results
(5)将数值中的假分数转换成真分数:get_Conversion()
实现代码:
def get_Conversion(fraction):#假分数转化真分数
if fraction.numerator%fraction.denominator==0:
return '%d'%(fraction.numerator/fraction.denominator)
elif fraction.numerator>fraction.denominator:
a=int(fraction.numerator/fraction.denominator)
b, c = fraction.numerator - a * fraction.denominator, fraction.denominator
return '%d%s%d%s%d' % (a,'’',b,'/',c)
else:
b, c = fraction.numerator, fraction.denominator
return '%d%s%d' % (b,'/',c)
实现代码:
def set_Formula(symbol,numerical,syb):#算术表达式
s=''
if syb>100:
if syb == 112 or syb ==212:
s = '(%s %s %s %s %s) %s %s = ' % (get_Conversion(numerical[0]), symbol[0],
get_Conversion(numerical[1]),symbol[1], get_Conversion(numerical[2]), symbol[2], get_Conversion(numerical[3]))
elif syb == 121 or syb ==122:
s = '(%s %s %s) %s %s %s %s = ' % (get_Conversion(numerical[0]), symbol[0],
get_Conversion(numerical[1]),symbol[1], get_Conversion(numerical[2]), symbol[2], get_Conversion(numerical[3]))
else:
s = '%s %s %s %s %s %s %s = ' % (get_Conversion(numerical[0]), symbol[0],
get_Conversion(numerical[1]),symbol[1], get_Conversion(numerical[2]), symbol[2], get_Conversion(numerical[3]))
elif syb>10:
if syb == 12:
s = '(%s %s %s)%s %s = ' % (get_Conversion(numerical[0]), symbol[0],
get_Conversion(numerical[1]), symbol[1], get_Conversion(numerical[2]))
else:
s = '%s %s %s %s %s = ' % (get_Conversion(numerical[0]), symbol[0],
get_Conversion(numerical[1]), symbol[1], get_Conversion(numerical[2]))
else :
s ='%s %s %s = ' % (get_Conversion(numerical[0]),symbol[0],get_Conversion(numerical[1]))
return s
实现代码:
def get_Formula(n,r):#生成题目和答案列表
Exercises,Answers,Exercises1,Exercises2=[],[],[],[]
x=1
while x<n+1:
symbol, syb, numerical,i = com(r).get_Arithmeticl()
results = numerical[0]
judge = True
for y in range(i):
calculate=get_Calculate(results,numerical[y+1],symbol[y])
if calculate>=0:#判断算式是否合法
answer=calculate
else:
judge=False
break
if judge:#查重
try:
num=Answers.index(answer)#第一个重复答案的索引
if operator.eq(Exercises1[num],symbol) and operator.eq(Exercises2[num],numerical):
pass
except ValueError as e:#可以写入
Answers.append(answer)
Exercises1.append(symbol)
Exercises2.append(numerical)
Exercises.append('%d. %s'%(x,set_Formula(symbol,numerical,syb)))
x+=1
else:pass
return Exercises,Answers
(8)filename为写入文件的路径,data为要写入数据列表:text_save()
实现代码:
def text_save(filename, data):#filename为写入文件的路径,data为要写入数据列表.
file = open(filename,'a')
file.seek(0)
file.truncate() # 清空文件
for x in data:
x='%s\n'%(x)
file.write(x)
file.close()
print('%s文件保存成功'%filename)
程序运行关系:
5.测试运行
运行代码(生成10道题目)
然后在本目录下生成Answers.txt、Answers.csv、Exercises.txt三个文件
生成10000条四则运算
验证生成的题目答案的正确性
(1)首先我们先随机生成十道计算题:
1. 1’3/7 ÷ 7 =
2. 2/3 × 1’3/5 =
3. 5/8 ÷ 2/9 =
4. 1 ÷ 6 =
5. 1’1/2 × 1’2/7 =
6. 1’1/2 - 1 + 3/10 =
7. (1’2/3 × 4 + 1’1/3) × 3/4 =
8. (5 + 1)÷ 4’1/2 =
9. (1/8 + 4’1/2)× 1 =
10. 7/9 - 2/3 - 5/9 + 1/2 =
(2)然后我们分别计算这些算数的结果
10/49
1’1/15
2’13/16
1/6
1’13/14
1’4/5
1’1/4
1’1/9
1/8
1’5/18
(3)查看生成的文件中所给的答案
1. 10/49
2. 1’1/15
3. 2’13/16
4. 1/6
5. 1’13/14
6. 1’4/5
7. 1’1/4
8. 1’1/9
9. 1/8
10. 1’5/18
(4)之后我们将我们计算的结果和生成的结果文件进行比对:运行校对程序,判断结果都是正确的
C:\Users\LibGem\AppData\Local\Programs\Python\Python37\python.exe C:/Users/LibGem/Desktop/第三次软件工程作业-最强版本/校对答案.py
Correct: 10 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Wrong: 0 []
Grade.txt文件保存成功
(5)此时如果我们将其中的三道题的计算结果的数据改成错误结果之后:(此处改动1,3,7,9题)
10/59
1’1/15
2’15/16
1/6
1’13/14
1’4/5
1’3/4
1’1/9
3/8
1’5/18
(6)之后再次运行程序
C:\Users\LibGem\AppData\Local\Programs\Python\Python37\python.exe C:/Users/LibGem/Desktop/第三次软件工程作业-最强版本/校对答案.py
Correct: 6 [2, 4, 5, 6, 8, 10]
Wrong: 4 [1, 3, 7, 9]
Grade.txt文件保存成功
可以发现在Wrong,即错误题号中出现了改动过结果的1,3,7,9题,即证明了程序校对的正确性
6.项目小结
自我总结(黄浩楠):在本次项目开发中,本人主要担任基本功能开发,在本次程序开发中,本人多次与队友在项目的设计上产生冲突。这种结队开发方式,与平时的自己蒙头打代码做自己的程序大不相同,个人开发时只要觉得自己的逻辑是对的就往下做就行了,最后只要结果做出来就ok了。但是在结队项目中,与队友的沟通至关重要,并且我也发现与队友的有效沟通可以大大提升代码开发速度,提高开发准确率,感谢我的队友,给我上了一课,让我体会到结对合作的意义。
何智聪(我):本次结对项目由我和我的队友黄浩楠同学共同完成,本次的程序主要是由黄浩楠进行编写,然后我进行相关的修改和程序的测试部分,在测试过程中出现了一系列问题,由于本人的python的编程技术并不精湛,所以在发现程序的测试运行相关问题的时候不能够独立的对其进行修改,我觉得这也是结对合作的意义所在。