姓名:苏麦耶姆·阿卜杜克热木
学号:3223004731
github 地址: https://gitee.com/suzette11/the-third-assignment/tree/master/
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 45 | 30 |
- Estimate | - 估计这个任务需要多少时间 | 60 | 70 |
Development | 开发 | 180 | 180 |
- Analysis | - 需求分析(包括学习新技术) | 40 | 30 |
- Design Spec | - 生成设计文档 | 45 | 45 |
- Design Review | - 设计复审(和同事审核设计文档) | 30 | 20 |
- Coding Standard | - 代码规范(为目前的开发制定合适的规范) | 25 | 30 |
- Design | - 具体设计 | 60 | 90 |
- Coding | - 具体编码 | 180 | 300 |
- Code Review | - 代码复审 | 40 | 40 |
- Test | - 测试(自我测试,修改代码,提交修改) | 40 | 40 |
Reporting | 报告 | 60 | 90 |
- Test Report | - 测试报告 | 30 | 30 |
- Size Measurement | - 计算工作量 | 40 | 30 |
- Postmortem & Process Improvement Plan | - 事后总结,并提出过程改进计划 | 20 | 30 |
核心方法 | 功能 |
---|---|
init | 初始化并自动调用化简方法 |
simplify | 分数化简(处理假分数、负号、公约数) |
add/__sub__等 | 重载运算符,实现分数四则运算 |
to_string | 转换为规定格式字符串(如2'3/8) |
parse(静态方法) | 从字符串解析为Fraction对象 |
表达式生成模块
核心函数 | 功能 |
---|---|
generate_expressions(count, range_limit) | 生成指定数量的不重复表达式 |
generate_expression(op_count, range_limit) | 递归生成单个表达式(控制运算符数量 1-3 个) |
is_valid_expression(expr) | 验证表达式合法性(如减法非负、除法有效) |
get_expression_fingerprint(expr) | 生成表达式 “指纹” 用于去重(标准化后哈希) |
normalize_expression(expr) | 标准化表达式(移除括号、排序+/×操作数) |
计算模块
核心函数 | 功能 |
---|---|
calculate_expression(expr) | 计算表达式结果(返回Fraction对象) |
infix_to_postfix(infix) | 中缀表达式转后缀表达式(Shunting-yard 算法) |
evaluate_postfix(postfix) | 计算后缀表达式结果(基于栈实现) |
依赖关系:
main.py 依赖所有模块,是流程控制中心;
expression_generator.py 依赖 calculator.py(验证表达式合法性)和 fraction.py(生成随机分数);
calculator.py 依赖 fraction.py(所有计算基于Fraction类);
file_operate.py 依赖 calculator.py(验证答案时重新计算正确结果)。
关键函数流程图
1.分数类
class Fraction:
def init(self, numerator=0, denominator=1, integer=0):
self.integer = integer # 整数部分
self.numerator = numerator # 分子
self.denominator = denominator # 分母
self.simplify() # 初始化时自动化简
def simplify(self):"""化简分数,处理假分数为带分数"""# 处理分母为0的情况if self.denominator == 0:raise ValueError("分母不能为0")# 确保分母为正数if self.denominator < 0:self.numerator *= -1self.denominator *= -1# 合并整数部分和分数部分(假分数处理)total_num = self.integer * self.denominator + self.numeratorself.integer = 0self.numerator = total_num# 提取整数部分if abs(self.numerator) >= self.denominator:self.integer = self.numerator // self.denominatorself.numerator = self.numerator % self.denominator# 化简分数部分if self.numerator != 0:gcd_val = self.gcd(abs(self.numerator), self.denominator)self.numerator //= gcd_valself.denominator //= gcd_val# 处理整体为0的情况if self.integer == 0 and self.numerator == 0:self.denominator = 1@staticmethod
def gcd(a, b):"""最大公约数计算"""while b:a, b = b, a % breturn adef __add__(self, other):"""加法运算"""# 转换为假分数num1 = self.integer * self.denominator + self.numeratornum2 = other.integer * other.denominator + other.numeratorden1, den2 = self.denominator, other.denominator# 通分计算new_num = num1 * den2 + num2 * den1new_den = den1 * den2return Fraction(new_num, new_den)# 其他运算符实现(减法、乘法、除法)类似def __ge__(self, other):"""大于等于比较,确保减法不出现负数"""num1 = self.integer * self.denominator + self.numeratornum2 = other.integer * other.denominator + other.numeratorreturn num1 * other.denominator >= num2 * self.denominatordef to_string(self):"""转换为规定格式的字符串"""if self.integer != 0:if self.numerator == 0:return f"{self.integer}"else:return f"{self.integer}'{self.numerator}/{self.denominator}"else:if self.numerator == 0:return "0"else:return f"{self.numerator}/{self.denominator}"
2.表达式生成器
def generate_expression(operator_count, range_limit):
"""递归生成表达式"""
if operator_count == 0:
# 生成数字(自然数或分数)
return generate_number(range_limit)
# 随机选择运算符
op = random.choice(['+', '-', '×', '÷'])# 分配运算符到左右子表达式
left_ops = random.randint(0, operator_count - 1)
right_ops = operator_count - 1 - left_opsleft_expr = generate_expression(left_ops, range_limit)
right_expr = generate_expression(right_ops, range_limit)# 处理减法(确保被减数 >= 减数)
if op == '-':left_val = evaluate_expression(left_expr)right_val = evaluate_expression(right_expr)if left_val < right_val:left_expr, right_expr = right_expr, left_expr# 处理除法(确保结果为真分数)
elif op == '÷':left_val = evaluate_expression(left_expr)right_val = evaluate_expression(right_expr)# 检查除法是否合法(结果为分数且除数不为0)if not is_valid_division(left_val, right_val):return generate_expression(operator_count, range_limit)# 随机添加括号
if random.random() < 0.3 and left_ops > 0:left_expr = f'({left_expr})'
if random.random() < 0.3 and right_ops > 0:right_expr = f'({right_expr})'# 对+和×进行排序,避免重复题目
if op in ['+', '×']:# 标准化处理,确保a+b和b+a被视为同一题目if should_swap(left_expr, right_expr):left_expr, right_expr = right_expr, left_exprreturn f"{left_expr} {op} {right_expr}"
3.题目去重机制
def normalize_expression(expr):
"""将表达式标准化,用于去重判断"""
# 移除括号(简化处理)
expr = expr.replace('(', '').replace(')', '')
# 处理加法和乘法的交换性
tokens = expr.split()
if len(tokens) == 3 and tokens[1] in ['+', '×']:# 对操作数排序,确保a+b和b+a具有相同的标准化形式left, op, right = tokensif compare_expressions(left, right) > 0:return f"{right} {op} {left}"
return expr
def is_duplicate(expr, existing_exprs):
"""检查表达式是否重复"""
normalized = normalize_expression(expr)
return normalized in existing_exprs
4.答案验证功能
def validate_answers(exercise_file, answer_file):
"""验证答案并生成评分结果"""
correct = []
wrong = []
with open(exercise_file, 'r') as ef, open(answer_file, 'r') as af:exercises = [line.strip() for line in ef if line.strip()]answers = [line.strip() for line in af if line.strip()]for i, (exercise, user_answer) in enumerate(zip(exercises, answers), 1):# 提取表达式部分expr = exercise.split('=')[0].strip()# 计算正确答案correct_answer = evaluate_expression(expr).to_string()# 比较答案if user_answer == correct_answer:correct.append(i)else:wrong.append(i)# 写入评分结果
with open('Grade.txt', 'w') as f:f.write(f"Correct: {len(correct)} ({', '.join(map(str, correct))})\n")f.write(f"Wrong: {len(wrong)} ({', '.join(map(str, wrong))})\n")
性能分析图表
函数名 | 调用次数 | 累计时间 (秒) | 占比 |
---|---|---|---|
normalize_expression | 45218 | 8.23 | 32.1% |
evaluate_expression | 38762 | 6.57 | 25.7% |
generate_expression | 15623 | 4.12 | 16.1% |
Fraction.simplify | 98342 | 3.26 | 12.7% |
is_duplicate | 10000 | 1.89 | 7.4% |
其他函数 | - | 1.52 | 6.0% |
总结
采用 "实现一个功能,测试一个功能" 的策略,例如先完成分数类,通过单元测试验证后再开发表达式生成,降低了集成风险。
通过性能分析工具定位瓶颈(去重和计算占 80% 耗时),针对性优化而非盲目重构,提升了优化效率。