当前位置: 首页 > news >正文

软工第三次作业-结对作业

姓名:苏麦耶姆·阿卜杜克热木
学号: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(验证答案时重新计算正确结果)。

关键函数流程图
image

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% 耗时),针对性优化而非盲目重构,提升了优化效率。

http://www.hskmm.com/?act=detail&tid=35390

相关文章:

  • 20251020 之所思 - 人生如梦
  • Conda、pip以及虚拟环境在Jupyter中的打开方法
  • 以太坊账⼾模型的理解,合约账⼾、EOA账⼾认识
  • Luogu P12376「LAOI-12」Calculate 题解 [ 蓝 ] [ 贪心 ] [ 线性 DP ] [ 前缀和优化 ] [ 范德蒙德卷积 ]
  • 方格图路径计数 dp 的反射路径优化
  • 每日反思(2025_10_20)
  • java基础9-面向对象进阶
  • 企业信息化建设的钱都花在哪儿了?
  • 身份运算符
  • 位运算符
  • 关系运算符
  • 赋值运算符
  • 算术运算符
  • Inno Setup 打包脚本模板
  • LCR 155. 将二叉搜索树转化为排序的双向链表
  • 解释这些区块链核⼼概念:区块、交易、Merkle Tree、共识机制(PoW、PoS)、Gas Fee 原理1
  • Claude code cli 的think mode到底是啥?
  • 【VM虚拟机共享主机代理】2025年10月20日可以pass的一些配置
  • 玄机——Linux后门应急
  • 2025/10/20
  • UI弹窗遮罩屏蔽触发事件的处理
  • newDay13
  • 小整数的地址
  • 概率论
  • 一次XFS死锁问题分析
  • P11150 [THUWC 2018] 字胡串
  • 推荐系统与机器学习在会员服务中的应用
  • ManySpeech.MoonshineAsr 使用指南
  • 日志|JAVAWEB|maven
  • QT_基础