个人作业1——四则运算题目生成程序(基于控制台)
一、题目描述:
1. 使用 -n 参数控制生成题目的个数,例如
Myapp.exe -n 10 -o Exercise.txt
将生成10个题目。
2. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如
Myapp.exe -r 10
将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。
3. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。
4. 每道题目中出现的运算符个数不超过3个。
5. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,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,它们之间不能通过有限次交换变成同一个题目。
生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:
1. 四则运算题目1
2. 四则运算题目2
……
其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。
6. 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:
1. 答案1
2. 答案2
特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。
7. 程序应能支持一万道题目的生成。
8. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,并会输出所有题目中重复的题目,输入参数如下:
Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt -o Grade.txt
统计结果输出到文件Grade.txt,格式如下:
Correct: 5 (1, 3, 5, 7, 9)
Wrong: 5 (2, 4, 6, 8, 10)
Repeat:2
RepeatDetail:
(1) 2,45+32 Repeat 3,32+45
(2) 5,3+(2+1) Repeat 7,1+2+3
解释:
Correct: 5 ----5道题目正确,正确的题号 1,3,5,7,9
Wrong:5 -----5道题目错误,错误的题号 2,4,6,8,10
Repeat:2 2---组题目重复
(1) 第一组 题号2,题目 45+32 与题号3的题目重复,题号3为 32+45
(2)第二组 题号5,题目 3+(2+1) 与题号7的题目重复,题号7为 1+2+3
其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。
二、功能设计
主要实现以下几个功能:
1.随机生成整数或者分数,随机生成符号,括号,进行拼接,形成等式
2.对所形成的等式进行转换,从中缀表达式转换为后缀表达式
3.对后缀表达式进行计算
4.对等式进行查重
5.对提供的答案文件进行判断,找出错误和正确的题号和数量
6.对上面功能所产生的题目和答案进行写入文件
三、设计实现
有以下类
getneed: 获取随机数、随机符号
create: 生成等式
change : 中缀表达式转后缀表达式
compute : 对后缀表达式进行计算
contrast : 对给定的答案文件进行对照
_int_ : 主界面,并对各个类进行整合,实现功能
四、代码说明
主要代码有以下:
1.生成等式
1 def getExample(l): # 获取表达式 2 a = getNeed.getNum(l) 3 for i in range(getNeed.getChNum()): # 不包括上限 4 # print(i) 5 c = getNeed.getSignal() 6 gl = random.randint(0, 1) 7 if (gl == 1): 8 b = getNeed.getNum(l) 9 else: 10 b = random.randint(1, l) 11 b = "|%d|" % (b) 12 if (gl == 0): 13 a = "%s%s%s" % (b, c, a) 14 else: 15 a = "%s%s%s" % (a, c, b) 16 r = random.randint(0, 3) 17 if (r == 2): 18 a = '(' + a + ')' 19 view = ''.join(re.split('\|', a)) 20 21 return a, view
2.中缀表达式转后缀表达式
1 def mid_after(equation): # 中缀转后缀 2 expression = [] 3 ops = [] 4 i = 0 5 while (i < len(equation)): 6 # print(i) 7 if (equation[i] == '|'): # 是数字进表达式expression栈 8 index = equation.find('|', i + 1) # 在i+1后寻找| 9 num = equation[i + 1:index] 10 # print(num) 11 expression.append(num) 12 i = index + 1 13 elif (isCh(equation[i])): # 是运算符进行判断优先级 14 if (ops == []): 15 ops.append(equation[i]) 16 i += 1 17 else: 18 if (equation[i] == ')'): # 遇到右括号,栈内左括号以后的符号出栈 19 while (equation[i] == ')' and ops[len(ops) - 1] is not '('): 20 expression.append(ops[len(ops) - 1]) 21 ops.pop() 22 ops.pop() 23 i += 1 24 elif (GetPriority(equation[i], 0) > GetPriority(ops[len(ops) - 1], 1)): # 优先级大于栈顶符号加入栈 25 ops.append(equation[i]) 26 i += 1 27 else: 28 while (not ops == [] and GetPriority(equation[i], 0) <= GetPriority(ops[len(ops) - 1], 29 1)): # 优先级小于等于 出栈 30 expression.append(ops[len(ops) - 1]) 31 ops.pop() 32 ops.append(equation[i]) 33 i += 1 34 35 while (not ops == []): 36 expression.append(ops[len(ops) - 1]) 37 ops.pop() 38 # print(expression) 39 return expression
3. 后缀表达式进行计算
1 def fourComputer(expression): 2 st = [] # 数字进栈 3 i = 0 4 while (i < len(expression)): 5 ch = expression[i] 6 if (not change.isCh(ch)): 7 st.append(ch) 8 else: 9 a = st.pop() # 栈顶元素弹出 10 b = st.pop() # 继续弹出 11 if (ch == '+'): 12 answer = str(Fraction(a) + Fraction(b)) 13 st.append(answer) 14 elif (ch == "-"): 15 answer = str(Fraction(b) + Fraction(a)) 16 st.append(answer) 17 elif (ch == '*'): 18 answer = str(Fraction(a) * Fraction(b)) 19 st.append(answer) 20 elif (ch == "÷"): 21 answer = str(Fraction(b) / Fraction(a)) 22 st.append(answer) 23 i += 1 24 answer = false_true(st.pop()) 25 return answer
4.对给定答案文件进行对照
def contrast(path): answer = [] answer1 = [] with open('answer.txt') as file: for line in file: answer.append(line) with open(path) as file1: for line1 in file1: answer1.append(line1) l = len(answer) # 正确答案 l1 = len(answer1) # 对照答案 rnum = 0 # 正确数量 wnum = 0 # 错误数量 right = [] # 正确题号 wrong = [] # 错误题号 if (l > l1): for i in range(l1): if (answer[i] == answer1[i]): rnum += 1 right.append(i + 1) else: wnum += 1 wrong.append(i + 1) for j in range(l1, l): wnum += 1 wrong.append(j + 1) else: for i in range(l): if (answer[i] == answer1[i]): rnum += 1 right.append(i + 1) else: wnum += 1 wrong.append(i + 1) return rnum, wnum, right, wrong
五、测试运行
六、PSD统计:
PSP2.1 |
Personal Software Process Stages |
Time Senior Student |
Time |
|
Planning |
计划 |
30 |
20 |
|
· Estimate |
估计这个任务需要多少时间 |
800 |
700 |
|
Development |
开发 |
600 |
500 |
|
· Analysis |
需求分析 (包括学习新技术) |
10 |
5 |
|
· Design Spec |
生成设计文档 |
30 |
40 |
|
· Design Review |
设计复审 |
10 |
10 |
|
· Coding Standard |
代码规范 |
10 |
10 |
|
· Design |
具体设计 |
20 |
15 |
|
· Coding |
具体编码 |
600 |
500 |
|
· Code Review |
代码复审 |
10 |
10 |
|
· Test |
测试(自我测试,修改代码,提交修改) |
20 |
30 |
|
Reporting |
报告 |
30 |
60 |
|
· |
测试报告 |
10 |
10 |
|
· |
计算工作量 |
10 |
10 |
|
· |
并提出过程改进计划 |
5 |
5 |
|
|
|
|
|
|
七、代码地址
https://gitee.com/Zdigi/four_operations/tree/master/calculate