结对作业
结对作业
1.
吴佩泽3119005478
更多操作这个作业属于哪个课程 | 首页 - 信安1912-软件工程 - 广东工业大学 - 班级博客 - 博客园 (cnblogs.com) |
---|---|
这个作业要求在哪里 | 结对项目 - 作业 - 信安1912-软件工程 - 班级博客 - 博客园 (cnblogs.com) |
这个作业的目标 | 完成简单四则运算生成器 |
队友 | 纯路人 |
2.
*PSP2.1* | *Personal Software Process Stages* | *预估耗时(分钟)* | *实际耗时(分钟)* |
---|---|---|---|
Planning | 计划 | 250 | 200 |
· Estimate | · 估计这个任务需要多少时间 | 200 | 180 |
Development | 开发 | 695 | 610 |
· Analysis | · 需求分析 (包括学习新技术) | 120 | 60 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 25 | 30 |
· Design | · 具体设计 | 120 | 60 |
· Coding | · 具体编码 | 300 | 360 |
· Code Review | · 代码复审 | 40 | 20 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 50 |
Reporting | 报告 | 30 | 30 |
· Test Report | · 测试报告 | 10 | 10 |
· Size Measurement | · 计算工作量 | 10 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 10 | 10 |
合计 | 975 | 840 |
3.效能分析
生成10000个算数表达式
4.设计实现过程
5.代码说明
(1)myapp.py
from Generate_topic import *
from Grade import *
import argparse
import os
parser = argparse.ArgumentParser(description="小学四则运算自动生成器")#命令行参数输入
parser.add_argument('-n', '-na', type=str, default=0, help='控制生成题目的个数')
parser.add_argument('-r', '-ra', type=str, default=0, help='题目中数值(自然数、真分数和真分数分母)的范围')
parser.add_argument('-o', '-oa', type=str, default=0,help='控制生成运算符的个数')
parser.add_argument('-e', '-ea', type=str, default="", help='题目文件')
parser.add_argument('-a', '-aa', type=str, default="", help='答案文件')
args = parser.parse_args()
n = int(args.n)
r = int(args.r)
o = int(args.o)
e = args.e
e = e.strip()
a = args.a
a = a.strip()
if os.path.exists(e) and os.path.exists(a):
print("核对答案后文件将保存到Grade.txt")
grade = Check(e,a)
else:
operatorNum = num_topic(n, r, o) # 将输入的参数传入num_topic()函数
os.system("pause")
(2)Generate_topic.py
from size_topic import *
def num_topic(times,r,randomNum,filename1='Exercise.txt',filename2='Answer.txt'):
"""用户输入"""
operator_num = randomNum
if operator_num < 1 or operator_num > 3:
print("请重新输入(1,2,3)") # 本程序仅支持1~3个符号运算
elif operator_num == 1:
one_size_topic(times,r,filename1='Exercise.txt',filename2='Answer.txt') # 转到单符号运算
elif operator_num == 2:
double_size_topic(times,r,filename1='Exercise.txt',filename2='Answer.txt') # 转到双符号运算
elif operator_num == 3:
triple_size_topic(times,r,filename1='Exercise.txt',filename2='Answer.txt') # 转到三符号运算
(3)size_topic.py(以双运算符号为例)
def double_size_topic(times,r,filename1='Exercise.txt',filename2='Answer.txt'):
"""双运算符号"""
q = 0
if r < 0:
print("请输入自然数")
elif r > 10:
print("请输入小于零的自然数")
"""限定r范围,防止小学生不会计算"""
while q < times:
Operation_symbol = ['+', '-', '*', '÷']
t = []
num = np.random.randint(4, size=2)
t = list(num)#对数组升序排序
t1 = getNonRepeatList1(t)
n1 = random.randint(0, r)
n2 = random.randint(0, r)
n3 = random.randint(0, r)
result = 0
if len(t1) > 1:#将数组经筛选后长度大于1的再次筛选,保证生成题目数量为输入值
first = Operation_symbol[t1[0]]
second = Operation_symbol[t1[1]]
if t == [0, 1]: # 加减法组合
n4 = n1 + n2
n4, n3 = max(n4, n3), min(n4, n3)
result = (n1 + n2) - n3
q+=1
elif t == [0, 2]: # 加乘法组合
result = (n1 + n2) * n3
q+=1
elif t == [0, 3]: # 加除法组合
if n3 != 0:
result = (n1 + n2) / n3
q+=1
if result % 1 == 0:#若能整除1,则直接取整数部分
result = int(result)
elif result < 1:
result = getTrueFractionSmall(result) # 实现小于1的小数化成真分数
else:
result = getTrueFractionBig(result)#实现大于1的小数化成真分数
elif t == [1, 2]: # 减乘法组合
n1, n2 = max(n1, n2), min(n1, n2)#防止结果出现负数,用max(),min()使n1>n2
result = (n1 - n2) * n3
q+=1
elif t == [1, 3]: # 减除法组合
if n3 != 0: # 除数不能为零
n1, n2 = max(n1, n2), min(n1, n2)#防止结果出现负数,用max(),min()使n1>n2
result = (n1 - n2) / n3
q += 1
if result % 1 == 0:
result = int(result)
elif result < 1:
result = getTrueFractionSmall(result) # 实现小于1的小数化成真分数
else:
result = getTrueFractionBig(result)
elif t == [2, 3]: # 乘除法组合
if n3 != 0: # 除数不能为零
result = (n1 * n2) / n3
q += 1
if result % 1 == 0:#若能整除1,则直接取整数部分
result = int(result)
elif result < 1:
result = getTrueFractionSmall(result) # 实现小于1的小数化成真分数
else:
result = getTrueFractionBig(result) #实现大于1的小数化成真分数
Exercises_writer1(filename1,q,n1,first,n2,second,n3)#调用File.py里的函数保存题目
Answers_writer1(filename2,q,n1,first,n2,second,n3,result)#调用File.py里的函数保存题目和答案
return r,times
(4)File.py(以双符号运算为例)
def Exercises_writer1(filename1,q,n1,first,n2,second,n3):
"""实现(x+y)*p类似的式子,并输出式子为filename1.txt"""
with open(filename1, 'a') as Exercises:
Exercises.write(str(q) + '.' + '(' + str(n1) + str(first) + str(n2) +')' + str(second) + str(n3) + '=' + '\n')
def Answers_writer1(filename2,q,n1,first,n2,second,n3,result):
"""实现(x+y)*p类似的式子,并输出式子及答案为filename2.txt"""
with open(filename2, 'a') as Answers:
Answers.write(str(q) + '.' + '(' + str(n1) + str(first) + str(n2) +')' + str(second) + str(n3) + '=' + str(result) + '\n')
(5)Grade.py
from fractions import Fraction
import sys
def Check(filename1,filename2,filename3='Grade.txt'):
"""filename1.txt与filename2.txt相比较,得出正确数"""
num=0
with open(filename1) as file01:
for line in file01:
num=num+1
# print(num)
# 计算一共有几行
with open(filename1,'r') as x ,open(filename2,'r') as y:
line1=[]
line2=[]
line1=x.readlines()
line2=y.readlines()
c = 0
w = 0
correct_topic =[]
wrong_topic = []
for i in range(num):#for循环遍历
if line1[i]==line2[i]:
c += 1
correct_topic.append(str(i+1))
else:
w += 1
var=str(i+1)
wrong_topic.append(str(i+1))
temp = sys.stdout #标准输出管道
file = open(filename3,'w')#将标准输出管道连到打开的文件
sys.stdout = file
print("Correct: ", str(c), '(', end='')
print(*correct_topic, sep=',', end='')
print(')')
print("Wrong: ", str(w), '(', end='')
print(*wrong_topic, sep=',', end='')
print(')')
sys.stdout.close()#关闭管道,所以,使用print 输出的数据,本来是存放在管道中,close()之后,全部写入文件中
sys.stdout = temp
return filename1,filename2
(6)List.py
from fractions import Fraction
def getNonRepeatList1(data):
"""数组去重升序排序"""
return list(set(data))
def getTrueFractionBig(num):
"""获取大于一的真分数"""
t = 0
while num > 0:
if num > 1:
num -= 1
t += 1
else:
num = Fraction(num).limit_denominator(1000000000000000000000)#将小数化成分数
break
return str(t) + "'" + str(num)
def getTrueFractionSmall(num):
"""获取小于一的真分数"""
while True:
num = Fraction(num).limit_denominator(100000000)#将小数化成分数
break
return str(num)
6.测试运行
使用 -n 参数控制生成题目的个数,例如
Myapp.exe -n 10
将生成10个题目。
使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如
Myapp.exe -r 10
将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。
生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1− e2的子表达式,那么e1≥ e2。
用比较函数使在减法时不会产生负数
生成的题目中如果存在形如e1÷ e2的子表达式,那么*其结果应是真分数*。
可以看出在结果大于1时,能化成真分数
小于一时也能化成真分数
*每道题目中出现的运算符个数不超过3个。*
同时我用-o num 来生成运算符的个数,1~3均可生成
程序一次运行生成的题目不能重复,*即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目*。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。*3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。*
暂无解决办法
在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answer.txt文件,格式如下
程序应能支持一万道题目的生成。
程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:
由于只改了后面的答案,所以正确数较多,输出格式也与要求相符
代码测试
import unittest
from Generate_topic import *
import re
filename = "Exercise.txt"
class MyTestCase(unittest.TestCase):
def test_something1(self):
filename = "Exercise.txt"
test1 = num_topic(10,10,3)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('10.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('10.','10.') # 通过测试
else:
pass#反之不通过
def test_something2(self):
filename = "Exercise.txt"
test1 = num_topic(9,5,1)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('9.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('9.','9.') # 通过测试
else:
pass#反之不通过
def test_something3(self):
filename = "Exercise.txt"
test1 = num_topic(4, 8, 3)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('4.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('4.','4.') # 通过测试
else:
pass#反之不通过
def test_something4(self):
filename = "Exercise.txt"
test1 = num_topic(7, 5, 2)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('7.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('7.','7.') # 通过测试
else:
pass#反之不通过
def test_something5(self):
filename = "Exercise.txt"
test1 = num_topic(8, 4, 2)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('8.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('8.','8.') # 通过测试
else:
pass#反之不通过
def test_something6(self):
filename = "Exercise.txt"
test1 = num_topic(9, 9, 1)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('9.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('9.','9.') # 通过测试
else:
pass#反之不通过
def test_something7(self):
filename = "Exercise.txt"
test1 = num_topic(5, 4, 3)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('5.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('5.','5.') # 通过测试
else:
pass#反之不通过
def test_something8(self):
filename = "Exercise.txt"
test1 = num_topic(7, 4, 1)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('7.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('7.','7.') # 通过测试
else:
pass#反之不通过
def test_something9(self):
filename = "Exercise.txt"
test1 = num_topic(8, 4, 3)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('8.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('8.','8.') # 通过测试
else:
pass#反之不通过
def test_somethin10(self):
filename = "Exercise.txt"
test1 = num_topic(3, 5, 2)
with open(filename, 'r') as x:
line1 = []
line1 = x.readlines()
line2 = []
line2.append(re.match('3.', line1[-1]).span())#匹配正则表达式,看line[]数组最后一项是否等于生成题号
if (0, 3) in line2:#若line[]数组最后一项是否等于生成题号
self.assertEqual('3.','3.') # 通过测试
else:
pass#反之不通过
if __name__ == '__main__':
unittest.main()
我们可以看到,十个测试都通过了,说明我们的生成数量是等于输入的n值
7.项目小结
(1)这是本人第一次用python编程,感觉python比java容易入手,而且pycharm也有很多有用的插件,能直接检测性能。
(2)在接近完成本程序时,发现想要随机生成符号数不同的算术表达式非常难,要用两个while循环,即n=10时会生成100个算