ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python实现自动生成小学四则运算题目

2020-09-20 23:32:27  阅读:259  来源: 互联网

标签:formular 题目 Python self 四则运算 char str operator stack


Python实现自动生成小学四则运算题目

 

Github地址:

https://github.com/RNG-Wh1t3zZ/air-force-one-lbw/blob/master/zy1.py

题目描述:

  通过python语言编写一个能够自动生成小学四则运算的程序(注意是给小学生用的,要是结果出现负数的话他们会很迷茫的!),同时,除了整数外,还要支持真分数的四则运算。

Psp表格:

第一次作业PSP

任务内容

计划完成需要的时间(min)

实际完成需要的时间(min)

Planning

计划

60

60

 Estimate

估计这个任务需要多少时间,并规划大致工作步骤

20

30

Analysis

需求分析 (包括学习新技术)

40

80

Design

具体设计

30

40

Coding

具体编码

300

500

test

测试(自我测试,修改代码,提交修改)

150

200

Postmortem & Process

Improvement Plan

事后总结 ,并提出过程改进计划

25

50

Summary

合计

 

625

 

960

1.程序设计

生成简单的四则运算题目需要两个整数或是分数,为了将答案与算式分类,用两个列表储存。q[]用来存储问题,ans[]用来存储答案。我们可以通过random模块生成一定区间里的随机数,分数也可以通过随机生成分子和分母的形式随机生成。同时分数可以使用Fraction模块,可以同时实现分数与整数的运算以及分子和分母的约分。

下面是各个函数的代码:

2.实现代码

# -*- coding: utf-8 -*-
'''
* @Author : lbw
* @Date : 2020-09-19 15:57:48
* @version : 1.0
* @Description : 小工具
* @LastEditTime : 2020-09-20 20:49:30
'''

import random
import datetime
import argparse
import re
from fractions import Fraction

def OPT(up_limit=10, oper_num=2, oper_variety=4, has_fraction=True):
'''
* 设置参数

* @param up_limit {int} 操作数数值上限

* @param oper_num {int} 操作数个数

* @param oper_variety {int} 运算符种类

* @param has_fraction {bool} 是否带有分数
'''
parse = argparse.ArgumentParser()
# 操作数数值上限
parse.add_argument('--up_limit', type=int, default=up_limit)
# 操作数个数
parse.add_argument('--oper_num', type=int, default=oper_num)
# 运算符种类
parse.add_argument('--oper_variety', type=int, default=oper_variety)
# 是否带有分数
parse.add_argument('--has_fraction', type=bool, default=has_fraction)

return parse.parse_args(args=[])

class GeneralFormular:
'''
* 生成算式

* @param opt {OPT} 参数
'''
def __init__(self, opt):
self.opt = opt

# @profile
def catFormula(self, operand1, operator, operand2):
'''
* 连接算式

* @param operand1 {str} 操作数1

* @param opertor {str} 运算符

* @param operand2 {str} 操作数2

* @return {str}
'''

return "{}{}{}".format(operand1, operator, operand2)

# @profile
def getRandomIntOperand(self):
'''
* 返回随机整数操作数

* @return {int}
'''
return random.randint(0, self.opt.up_limit)

# @profile
def getRandomFractionOperand(self):
'''
* 返回随机分数操作数

* @return {str}
'''
num01 = self.getRandomIntOperand()
num02 = self.getRandomIntOperand()
while num01 == num02 or num02==0:
num02 = self.getRandomIntOperand()
while num01 == 0:
num01 = self.getRandomIntOperand()

# 保证分数为真分数
if num01 < num02:
return str(num01) + "/" + str(num02)
else:
return str(num02) + "/" + str(num01)

# @profile
def getRandomOperator(self):
'''
* 返回随机运算符

* @return {str}
'''
index = random.randint(0, self.opt.oper_variety-1)
if index == 0:
return '+'
elif index == 1:
return '-'
elif index == 2:
return '×'
else:
return '÷'

# @profile
def getOriginFormular(self):
'''
* 生成整数源算式

* @return {str}
'''
tmp = self.getRandomIntOperand()
for i in range(self.opt.oper_num-1):
tmp = self.catFormula(tmp, self.getRandomOperator(), self.getRandomIntOperand())

# 去掉'÷0'
while(True):
if '÷0' in tmp:
tmp = tmp.replace('÷0', '÷'+str(self.getRandomIntOperand()))
else:
break

return tmp

# @profile
def insertBracket(self, formular):
'''
* 插入括号

* @param formular {str} 源算式

* @return {str}
'''
# print(formular)

# 若只包含+号 或 只有两个操作数 则不用加括号
if self.opt.oper_variety <= 2 or self.opt.oper_num == 2:
return formular
# 若不包含×÷ 则不用加括号
if '×' not in formular and '÷' not in formular:
return formular

# 操作数列表
operand_list = re.split("[-|+|×|÷]", formular)
# 操作符列表
operator_list = re.split("[!0-9]", formular)
# 去掉空字符
while '' in operator_list:
operator_list.remove('')
# print(operand_list, operator_list)

# 添加括号
new_formular = ""
flag = 0
for i in range(len(operator_list)):
oper = operator_list.pop(0)
if oper == '-' or oper == '+':
if flag == 0:
new_formular += "("
flag = 1
new_formular += (str(operand_list.pop(0)) + str(oper))
else:
new_formular += str(operand_list.pop(0))

if flag == 1:
new_formular += ")"
flag = 0

new_formular += str(oper)
# print(operand_list, operator_list, new_formular)

new_formular += str(operand_list.pop(0))
if flag == 1:
new_formular += ")"

return new_formular

# @profile
def replaceFraction(self, formular):
'''
* 带入分数

* @param formular {str} 源算式,可能包含括号

* @return {str}
'''

# 带入分数个数
fraction_num = 1
if self.opt.oper_num > 2:
fraction_num = (self.opt.oper_num - 1) / 2
# 操作数列表
operand_list = re.split("[-|+|×|÷|(|)]", formular)
# 去掉空字符
while '' in operand_list:
operand_list.remove('')
index = random.randint(0, len(operand_list)-1)

formular = formular.replace(str(operand_list[index]), self.getRandomFractionOperand())

return formular

# @profile
def solve(self):
'''
* 整合生成算式的后缀表达式,带括号

* @return {str}
'''
# 生成原生算式
ori_formular = self.getOriginFormular()
# 添加括号
bra_formular = self.insertBracket(ori_formular)
# 带入分数
if self.opt.has_fraction:
bra_formular = self.replaceFraction(bra_formular)

return bra_formular

class ComputeFormular:
'''
* 计算算式的值
'''
def __init__(self):
pass

# @profile
def getPostFormular(self, formular):
'''
* 中缀表达式转为后缀表达式

* @param formular {str} 中缀表达式

* @return {str}
'''
# 运算符栈
operator_stack = []

# 后缀表达式
post_formular = ""

# 中缀表达式转为后缀表达式
i = 0
while i < len(formular):
char = formular[i]
# print("1: ", i, char, operator_stack, post_formular)
if char == '(':
operator_stack.append(char)
i += 1
# print("2: ", i, operator_stack, post_formular)
elif char == ')':
tmp_char = operator_stack.pop()
while tmp_char != '(':
post_formular += tmp_char
if len(operator_stack) != 0:
tmp_char = operator_stack.pop()
else:
break
i += 1
# print("3: ", i, operator_stack, post_formular)
elif char == '+' or char == '-':
try:
tmp_char = operator_stack.pop()
except Exception as e:
pass
while len(operator_stack) != 0:
if tmp_char != '(':
post_formular += tmp_char
if len(operator_stack) != 0:
tmp_char = operator_stack.pop()
else:
break
else:
operator_stack.append(tmp_char)
break
operator_stack.append(char)
i += 1
# print("4: ", i, operator_stack, post_formular)
elif char == '×' or char == '÷':
while len(operator_stack) != 0:
tmp_char = operator_stack.pop()
if tmp_char== '×' or tmp_char == '÷':
post_formular += tmp_char
if len(operator_stack) != 0:
tmp_char = operator_stack.pop()
else:
break
else:
break
operator_stack.append(char)
i += 1
# print("5: ", i, operator_stack, post_formular)
# 存在数字时
else:
# print("6: ", i, operator_stack, post_formular)
while char >= '0' and char <= '9' or char == '/':
post_formular += char
i += 1
if i < len(formular):
char = formular[i]
else:
break
post_formular += '#'
# print("7: ", i, operator_stack, post_formular)

# 若符号栈不为空则循环
while len(operator_stack) != 0:
tmp_char = operator_stack.pop(0)
post_formular += tmp_char
# print("8: ", i, operator_stack, tmp_char)

# print(post_formular)
return post_formular

# @profile
def calcFormular(self, formular):
'''
* 计算算式的值

* @param formular {str} 后缀表达式

* @return {str}
'''
# 操作数栈
operand_stack = []
i = 0
while i < len(formular):
if formular[i] == '+':
num01 = operand_stack.pop()
num02 = operand_stack.pop()
result = Fraction(num02) + Fraction(num01)
operand_stack.append(result.__str__())
elif formular[i] == '-':
num01 = operand_stack.pop()
num02 = operand_stack.pop()
result = Fraction(num02) - Fraction(num01)
operand_stack.append(result.__str__())
elif formular[i] =='×':
num01 = operand_stack.pop()
num02 = operand_stack.pop()
result = Fraction(num02) * Fraction(num01)
operand_stack.append(result.__str__())
elif formular[i] == '÷':
num01 = operand_stack.pop()
num02 = operand_stack.pop()
try:
result = Fraction(num02) / Fraction(num01)
operand_stack.append(result.__str__())
except Exception as e:
# print('Error: 除零错误!')
return "NaN"
else:
number = ""
while formular[i] >= '0' and formular[i] <= '9' or formular[i] == '/':
number += formular[i]
if i < len(formular):
i += 1
else:
i -= 1
break
operand_stack.append(number)

i += 1

return operand_stack.pop()

# @profile
def solve(self, formular):
'''
* 整合计算中缀表达式的值

* @param formular {str} 后缀表达式

* @return {str}
'''
# 转为后缀表达式
post_formular = self.getPostFormular(formular)
value = self.calcFormular(post_formular)

return value


if __name__ == "__main__":
opt = OPT(up_limit=10, oper_num=5, has_fraction=False)
gf = GeneralFormular(opt)
# gf.getRandomIntOperand()
# gf.getRandomFractionOperand()
# gf.getRandomOperator()
# formular = gf.getOriginFormular()
# new_formular = gf.insertBracket(formular)
# fra_formular = gf.replaceFraction(new_formular)
# print("源算式:", formular)
# print("加括号:", new_formular)
# print("换分数:", fra_formular)

cf = ComputeFormular()
# post_formular = cf.getPostFormular(fra_formular)
# value = cf.calcFormular(post_formular)
# print("后缀式:", post_formular)
# print("结果:", value)

fra_formular = gf.solve()
print("中缀式:", fra_formular)
value = cf.solve(fra_formular)
print("结果:", value)

 

  

3.程序运行结果

标签:formular,题目,Python,self,四则运算,char,str,operator,stack
来源: https://www.cnblogs.com/abing123/p/13702991.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有