这个作业属于哪个课程 | 计科22级12班 |
---|---|
这个作业的要求在哪里 | 结对项目 |
这个作业的目标 | 实现小学四则运算的程序,在合作中完成项目设计结对项目 |
成员
姓名 | 学号 |
---|---|
黄英琦 | 3122004909 |
张怀坤 | 3122004926 |
Github地址
预估设计时间
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 70 |
Estimate | 估计这个任务需要多少时间 | 800 | 940 |
Development | 开发 | 60 | 100 |
Analysis | 需求分析 (包括学习新技术) | 85 | 70 |
Design Spec | 生成设计文档 | 24 | 34 |
Design Review | 设计复审 | 15 | 25 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 24 | 30 |
Design | 具体设计 | 90 | 140 |
Coding | 具体编码 | 80 | 98 |
Code Review | 代码复审 | 20 | 44 |
Test | 测试(自我测试,修改代码,提交修改 | 70 | 90 |
Reporting | 报告 | 55 | 45 |
Test Repor | 测试报告 | 30 | 40 |
Size Measurement | 计算工作量 | 65 | 70 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 25 |
效能分析
改进性能花费时间
7h
性能图
改进思路
首先是对于生成重复题目的算法,原先的思路是检测两个题目的运算符数量,位置,算式中数字组成相同去判断是否重复,但这样会出现一些式子实际重复但检测出来没重复,所以在此检测基础上,通过先寻找两个式子中最后一步运算,得到两个新式子——包含2个数与最后运算符号,如果式子一模一样,继续判断,将原式子以最后运算符位置拆成两个式子,再判断对应边新生成的式子是否一致(即两原式子对于最后符号的左侧一致,右侧也一致),直到新的式子是单个数,特别的,在拆分时,若当前运算为加法或乘法,需考虑交换的情况,即左侧的等于右侧,右侧等于左侧的情况
消耗最大函数
genarate_exerises #生成题目
改进后的性能图
设计实现过程
模块
- 生成算式模块
- 计算正确答案模块
- 检测重复答案模块
- 判定答案对错模块
函数
- def getNumber(maxNum):
随机生成整数或分数 - def getOperator(count):
生成指定数量的运算符列表 - def getNoBracketFormula(parameter_list, operator_list):
生成不带括号的算式 - def getBracketFormula(parameter_list, operator_list):
生成带括号的算式 - def getrandomFormula(maxNum):
随机生成算式 - def replace_mixed_numbers(input_string):
将算式中的带分数替换为假分数 - def infix_to_postfix(expression):
中缀表达式转换为后缀表达式 - def evaluate_postfix(postfix_expression):
计算后缀表达式的值 - def evaluate_expression(expr):
计算表达式的值 - def improper_to_mixed(improper_fraction):
假分数化为带分数 - def duplicate_check(expr,exercises):
重复检验 - def generate_exercises(num,range):
生成题目并保存到文件 - def grade_exercises(exercise_file, answer_file):
判定答案的正确性并统计结果 - def check(formula,formula_past):
进行算式的查重 - def isOperator(element):
判断是否是运算符 - def calculate( num1, num2, op ):
计算两数运算结果 - processeNumber( num ):
把带分数变假分数 - def comp(comp1,count):
比较最后一次运算式子是否相同 - def knowproxy(low):
判断符号的优先级 - def processeFormula( formula ):
将算式分割存入list
关系
先生成算式,再计算式子,把式子与答案分别写入对应文件。
- 在随机生成算式模块中:主程序调用getrandomFormula ,它调用getOperator 随机生成运算符数量和符号和getNumber随机生成数字,再调用getNoBracketFormula
getBracketFormula生成带括号或者不带括号的算式 - 在计算模块中:evaluate_expression计算算式结果,其调用infix_to_postfix
- 把算式转为后缀表达式,replace_mixed_numbers把带分数变假分数,evaluate_postfix
- 计算后缀表达式值,前一个调用duplicate_postfix详细每个步骤,最后evaluate_expression可调用improper_to_mixed把答案变带分数,
- 查重模块:如果生成的算式结果与之前的一致,则调用check进行查重,其先调用processeFormula 与isOperator进行运算符与数字拆分,再调用comp进行最后算式比较,其利用calculate计算两数结果,processeNumber将带分数转为假分数,knowproxy确定优先级来计算
- 判定答案对错模块:evaluate_expression对题目计算正确答案,再与answerfile.txt中传入的答案进行对比判定
- 写入文件模块:generate_exercises进行文件的写入
- 统计结果模块:grade_exercises进行问题与答案的统计,以及答案检查,并把结果写入文件
- 关键函数:getrandomFormula 与 evaluate_expression
流程图
- 随机生成算式算法流程图
- 计算算式结果算法流程图
代码说明
关键代码
思路
对于四则运算的算式生成,通过生成运算符再生成对应数量数字,穿插合并,再随机生成带括号和不带括号的式子。计算则是把式子先用栈把式子变为后缀表达式,再利用栈一步步运算式子,通过后缀表达式计算得到最后结果。
测试运行
测试用例
- python Myapp.py -n 10 -r 10
- python Myapp.py -e Exercises.txt -a Answers_test.txt
结果:Grade.txt
为什么你能确定你的程序是正确的
- 保证生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1− e2的子表达式,那么e1≥ e2:
一旦出现计算过程中出现减数大于被减数的情况,结果置为-1,生成的算式作废 - 保证生成的题目中如果存在形如e1÷ e2的子表达式,那么其结果应是真分数:
如果算式的结果是假分数,则化为带分数 - 保证每道题目中出现的运算符个数不超过3个:
在生成随机算式时,仅生成1~3个运算符 - 保证程序一次运行生成的题目不能重复
项目小结
首先是比较好的完成了代码的实现,把基本要求都实现了,部分代码的写作上有些 繁琐复杂,有改进的空间,而且由于两个人编写,有些代码难免会有重复,这是由于我们分工没有明确导致的,还有就是队友是第一次用Python编写所以会有些生疏,本次合作最大感受就是合作确实使项目工作量减少很多,但是一些分歧,和由于代码书写习惯不同的原因,使得合并代码与分析代码的速度慢了很多,当然,本次闪光点就是一起想出查重思路,以及利用合理编排,分工项目进行整合的连接比较有思路,有错误又能较清晰的修改。
标签:结对,项目,算式,生成,运算符,表达式,def,式子 From: https://www.cnblogs.com/skzhkk/p/18438550