软工第二次作业 ------ 结对项目
1.项目地址
| 成员 | 学号 | Github地址 |
|---|---|---|
| 黄浩楠 | 3119005461 | 作业项目地址 |
| 何智聪 | 3119005458 | https://github.com/OveOveOve/ |
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)
(6)算术表达式:get_Formula()
实现代码:
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
(7)生成题目和答案列表:get_Formula()
实现代码:
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文件保存成功

浙公网安备 33010602011771号