软工第二次作业

这个作业属于哪个课程 22计科12班
这个作业要求在哪里 结对项目
这个作业的目标 结对项目实现一个自动生成小学四则运算题目的命令行程序

GitHub地址:https://github.com/xian226/-four_operation

成员信息

姓名 学号
张颢严 3222004426
王睿娴 3222003968

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时 (分钟) 实际耗时 (分钟)
Planning 计划 60 60
·Estimate ·估计这个任务需要多少时间 30 30
Development 开发 480 600
·Analysis ·需求分析(包括学习新技术) 300 300
· Design Spec ·生成设计文档 60 60
·Design Review .设计复审 20 10
· Coding Standard ·代码规范(为目前的开发制定合适的规范) 10 10
·Design .具体设计 15 15
·Coding .具体编码 180 300
· Code Review ·代码复审 20 10
·Test ·测试(自我测试,修改代码,提交修改) 60 60
Reporting 报告 60 60
·Test Report ·测试报告 30 40
·Size Measurement ·计算工作量 15 10
·Postmortem & Process Improvement Plan ·事后总结,并提出过程改进计划 5 5
·合计 1345 1570

效能分析


程序中消耗时间最多的函数是,总调用次数为26次,消耗了76毫秒,占总时间的84.4%。其他调用时间较长的函数包括suffixToValue和<method 'exit' of '_io.IOBase' objects>,但它们的时间消耗较少,分别为3毫秒和1毫秒。
改进思路:由于文件I/O操作消耗了程序的大部分时间,84.4%的总时间都用于此。可以尝试减少I/O操作或合并I/O操作。

设计实现过程

(1)代码组织结构:

Product: 负责生成数学表达式,包括操作数和运算符。还负责去重和规范化输出表达式。
SuffixExpression: 将中缀表达式转换为后缀表达式,并计算后缀表达式的值。
BinaryTree: 用于生成和比较二叉树,帮助判断表达式的重复性。
Answer: 计算表达式的结果并与给定答案进行比对。

(2)类之间的关系

Product 类创建数学表达式,并通过 SuffixExpression 类进行计算。它还使用 BinaryTree 类来判断表达式的唯一性。
Answer 类使用 SuffixExpression 类来计算表达式结果,并验证这些结果。

(3)关键函数:

Product.creQuestion(): 生成表达式的主函数。
SuffixExpression.toSuffix(): 将中缀表达式转换为后缀表达式。
Answer.expression_result(): 计算一组表达式的值并写入答案文件。
Answer.check_answer(): 校对生成的答案与提供的答案。

(4)流程:

Product.creQuestion()
初始化表达式列表。
循环生成表达式。
随机生成操作数和运算符。
检查是否需要括号。
检查表达式是否重复。
计算表达式的值。
返回表达式列表。

SuffixExpression.toSuffix()
初始化操作符栈和后缀表达式栈。
遍历中缀表达式:
若是操作数,直接入栈。
若是操作符,按照优先级入栈并生成后缀表达式。
处理括号。
将栈中剩余操作符添加到后缀表达式。
返回后缀表达式。

Answer.expression_result()
读取表达式列表。
初始化答案文件。
遍历表达式,计算结果。
写入答案文件。

Answer.check_answer()
读取题目文件和答案文件。
对每个题目计算其结果。
比对答案,记录正确和错误的题号。
输出结果到评分文件。

代码说明

Product类

点击展开代码
class Product:
    def __init__(self, operRange, expressionNum):
        self.operRange = operRange
        self.operCount = 3
        self.expressionNum = expressionNum
        self.problemArray = self.creQuestion()
        self.normalizeExpression(self.problemArray)
构造函数初始化操作数范围、运算符数量和表达式数量。 调用 creQuestion() 方法生成表达式,并规范化输出。

生成表达式

点击展开代码
def creQuestion(self):
    expressionList = []
    i = 0
    while i < self.expressionNum:
        random_num_operation = random.randint(1, self.operCount)
        exp = []
        for j in range(random_num_operation + 1):
            exp.append(self.getOperNum() if j % 2 == 0 else self.generateOperation())
        expression = " ".join(exp)
        if not self.isRepeat(expressionList, expression):
            expressionList.append(expression)
            i += 1
    return expressionList
生成指定数量的表达式。 随机选择操作数和运算符构建表达式。 调用 isRepeat() 方法检查生成的表达式是否重复。

转换为后缀表达式

点击展开代码 ```python class SuffixExpression: def toSuffix(self): suffix_stack = [] ops_stack = [] infix = self.exp.split(' ') for item in infix: if item in ['+', '-', '×', '÷']: while ops_stack and ops_rule[item] <= ops_rule[ops_stack[-1]]: suffix_stack.append(ops_stack.pop()) ops_stack.append(item) elif item == '(': ops_stack.append(item) elif item == ')': while ops_stack and ops_stack[-1] != '(': suffix_stack.append(ops_stack.pop()) ops_stack.pop() # 弹出 '(' else: suffix_stack.append(item) while ops_stack: suffix_stack.append(ops_stack.pop()) return suffix_stack ```
通过栈结构实现中缀表达式到后缀表达式的转换。 操作符按优先级入栈,保证后缀表达式的正确性。

计算后缀表达式的值

点击展开代码 ```python def suffixToValue(self): stack_value = [] for item in self.re: if item in ['+', '-', '×', '÷']: n2 = stack_value.pop() n1 = stack_value.pop() result = self.cal(n1, n2, item) if result is False: return False stack_value.append(result) else: stack_value.append(Fraction(item)) # 处理数值 return stack_value[0] ```
遍历后缀表达式,计算结果。 使用栈结构存储操作数,遇到操作符时弹出相应的操作数进行计算。

计算表达式结果并写入文件

点击展开代码 ```python def expression_result(self, exp_list): if os.path.exists('Answer.txt'): with open('Answer.txt', 'r+') as file: file.truncate(0) for i, exp in enumerate(exp_list): suffixExpression = SuffixExpression(exp) exp_value = str(suffixExpression.suffixToValue()) + '\n' result = "Answer" + str(i + 1) + ': ' + exp_value with open('Answer.txt', 'a+', encoding='utf-8') as f: f.write(result) ```
读取表达式列表,计算每个表达式的结果。 将结果写入答案文件,便于后续检查。

运行结果

在终端输入:python main.py -n 10 -r 10
在Exercise.txt中生成随机的十道题目

在Answer.txt中生成题目对应的标准答案

将Exercise.txt中的题目复制到exercisefile.txt文件中,将做题答案写入answerfile.txt中

(此处故意将第2, 7, 9题写错)
之后再在终端中输入:python main.py -n 10 -r 10 -e exercisefile.txt -a answerfile.txt
在生成10道随机的题目,并且核对刚才十道题目的答案
结果如下:

项目小结

本次结对编程项目的目标是设计并实现一个小学四则运算题目自动生成器,包含生成题目、计算答案以及核对答案等功能。我们通过 Python 语言开发,并分工合作,共同推进项目的完成。整体项目涉及表达式生成、重复性检查、后缀表达式计算等多个模块的开发与集成。
我们在项目初期对模块进行了合理的分工,每人负责特定模块,并在关键点进行沟通。这样既提高了效率,也确保了每个模块的独立性和完整性。
代码规范与测试:在编写代码时,我们遵循了良好的代码规范,每个模块在编写完成后都进行了单独的测试,确保其功能的正确性和稳定性。这使得项目的集成过程相对顺利。
在项目开发中遇到的复杂问题,如重复表达式的检测、分数运算的处理等,我们通过频繁的讨论和及时的反馈解决了多个难题。
经验与教训
在项目进行过程中,我们发现一些初期未考虑到的需求(如分数的带括号计算等),导致我们需要临时调整部分模块的实现。在这方面,我们学到了在项目初期详细梳理需求的重要性。

posted @ 2024-09-28 22:38  xian226  阅读(17)  评论(0编辑  收藏  举报