结对作业

结对作业

1.

吴佩泽3119005478

更多操作这个作业属于哪个课程 首页 - 信安1912-软件工程 - 广东工业大学 - 班级博客 - 博客园 (cnblogs.com)
这个作业要求在哪里 结对项目 - 作业 - 信安1912-软件工程 - 班级博客 - 博客园 (cnblogs.com)
这个作业的目标 完成简单四则运算生成器
队友 纯路人

Github链接

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个算

posted @ 2021-10-18 23:32  %9;3  阅读(129)  评论(0编辑  收藏  举报