psp下的四则运算

psp:

psp 任务内容 计划完成需要的时间(min) 实际完成需要的时间(min)
Planning 计划 10 15
Estimate 估计这个任务需要多少时间,并规划大致工作步骤 6 6
Development 开发 120 120
Analysis 需求分析(包括学习新技术) 10 10
Design Spec 生成设计文档 20 20
Coding Standard 代码规范 5 8
Design 具体设计 15 22
Coding 具体编码 40 35
Code Review 代码复审 5 4
Test 测试(自我测试,修改代码,提交修改) 20 15
Reporting 报告 10 10
Test Report 测试报告 2 3

 

代码:

sizeyusuan代码:

import wx
from wx.core import CLEAR
from formula import OPT, GeneralFormular, ComputeFormular

class MyApp(wx.App):
def OnInit(self):
frame = wx.Frame(parent=None, title="四则运算生成器") # 新建框架
panel = wx.Panel(frame, -1) # 生成面板
Text = wx.StaticText(panel,-1,"请输入相关需求",pos=(150,2))

label1=wx.StaticText(panel,-1,"生成算式数量(>=1)",pos=(10,30)) #标签
text1=wx.TextCtrl(panel,-1,pos=(200,30),size=(180,20), #输入框
style=wx.TE_MULTILINE)

label2=wx.StaticText(panel,-1,"每个数值的上限(>=10)",pos=(10,60))
text2=wx.TextCtrl(panel,-1,pos=(200,60),size=(180,20),
style=wx.TE_MULTILINE)

label3=wx.StaticText(panel,-1,"操作数个数(>=2)",pos=(10,90))
text3=wx.TextCtrl(panel,-1,pos=(200,90),size=(180,20),
style=wx.TE_MULTILINE)

label4=wx.StaticText(panel,-1,"运算符种数(1~4)",pos=(10,120))
text4=wx.TextCtrl(panel,-1,pos=(200,120),size=(180,20),
style=wx.TE_MULTILINE)

label5=wx.StaticText(panel,-1,"是否要包含分数(0,1)",pos=(10,150))
text5=wx.TextCtrl(panel,-1,pos=(200,150),size=(180,20),
style=wx.TE_MULTILINE)

button = wx.Button(panel,-1, '确定', pos=(150, 180)) # 确定按钮位置

self.text1=text1 #方便跨函数调用
self.text2=text2
self.text3=text3
self.text4=text4
self.text5=text5

self.button1 = button
self.Bind(wx.EVT_BUTTON, # 绑定事件,如果是按钮被点击
self.GetInPut, # 激发的按钮事件
self.button1) # 激发的按钮

frame.Center()
frame.Show() # 显示
return True

def GetInPut(self,event): #事件的激发函数,获得输入
while True:

n = self.text1.GetValue()
try:
n = abs(int(n))
if n < 1:
wx.MessageBox("生成算式数量-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("生成算式数量-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break

up_limit = self.text2.GetValue()
try:
up_limit = abs(int(up_limit))
if up_limit < 10:
wx.MessageBox("每个数值的上限-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("每个数值的上限-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break

oper_num = self.text3.GetValue()
try:
oper_num = abs(int(oper_num))
if oper_num < 2:
wx.MessageBox("操作数个数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("操作数个数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break

oper_variety = self.text4.GetValue()
try:
oper_variety = abs(int(oper_variety))
if oper_variety < 1 or oper_variety > 4:
wx.MessageBox("运算符种数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("运算符种数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break

has_fraction = self.text5.GetValue()
try:
has_fraction = abs(int(has_fraction))
if has_fraction != 0 and has_fraction != 1:
wx.MessageBox("是否要包含分数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break
except Exception as e:
wx.MessageBox("是否要包含分数-[Eror]: Input illegal! Please input again... "\
, "INFO", wx.OK|wx.ICON_INFORMATION)
break

self.n = int(n)
self.up_limit = int(up_limit)
self.oper_num = int(oper_num)
self.oper_variety = int(oper_variety)
self.has_fraction = int(has_fraction)

self.solveFormular()
break

def solveFormular(self):
opt = OPT(self.up_limit, self.oper_num, self.oper_variety, self.has_fraction)

gf = GeneralFormular(opt)
cf = ComputeFormular()

formulars = []
results = []
for i in range(int(self.n)):
f = gf.solve()
formulars.append(" ".join(i for i in f) + " = ")
results.append(cf.solve(f))

self.formulars=formulars
self.results=results
self.displayFormular()

def displayFormular(self):
frame = wx.Frame(parent=None, title="计算界面", size=(500,500))
self.panel = wx.Panel(frame, -1) # 生成面板

self.Column = 30
self.Row = 10
self.N =len(self.formulars)
self.i = 0

self.GetResult()

frame.Center()
frame.Show() # 显示
return True

def GetResult(self): #显示题目和答题文本框
if self.Column >= 800:
self.Row += 500
self.Column = 30
T_label=wx.StaticText(self.panel,-1,"第{}题:".format(self.i+1) + self.formulars[self.i],pos=(self.Row,self.Column)) #标签
T_text=wx.TextCtrl(self.panel,-1,pos=(self.Row+340,self.Column),size=(100,20), #输入框
style=wx.TE_PROCESS_ENTER)
self.T_text = T_text

self.Bind(wx.EVT_TEXT_ENTER, self.judgeResult, T_text)

def judgeResult(self,event): #判断正误
self.result = self.T_text.GetValue()
self.Column += 30
if self.result == self.results[self.i]:
flag = "正确 √ √ √"
else:
flag = "错误❌❌❌"

T_label=wx.StaticText(self.panel,-1," 正确答案:{} 回答{}"\
.format(self.results[self.i], flag),pos=(self.Row,self.Column))

self.i += 1
try:
if self.i <= self.N-1:
self.Column = self.Column+30
self.GetResult()
else:
End_label=wx.StaticText(self.panel,-1," ---------答题结束--------- ",pos=(self.Row, self.Column+50))
End_label.SetFont(wx.Font(12, wx.SWISS))
except Exception as e:
return True

if __name__ == '__main__':
app = MyApp() # 启动
app.MainLoop() # 进入消息循环

 

formula代码:

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, be_negetive=False):
'''
* 设置参数

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

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

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

* @param has_fraction {bool} 是否带有分数

* @param be_negative {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)
# 可否存在负数
parse.add_argument('--be_negative', type=bool, default=be_negetive)

return parse.parse_args(args=[])

class GeneralFormular:
'''
* 生成算式

* @param opt {OPT} 参数
'''
def __init__(self, opt):
self.opt = opt
# 定义运算符
self.operator = ['+', '-', '×', '÷']

# @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 Fraction(num01, num02).__str__()
else:
return Fraction(num02, num01).__str__()

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

* @return {str}
'''
index = random.randint(0, self.opt.oper_variety-1)
return self.operator[index]

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

* @return {list}
'''
# 通过self.opt.oper_num控制操作数个数,循环调用catFormula()方法构造算式
formular = self.getRandomIntOperand()
for i in range(self.opt.oper_num-1):
formular = self.catFormula(formular, self.getRandomOperator(), self.getRandomIntOperand())

# 去掉'÷0'
while(True):
if '÷#0' in formular:
formular = formular.replace('÷#0', '÷#' + str(self.getRandomIntOperand()))
else:
break
# 通过'#'分割生成列表
formular_list = formular.split('#')

return formular_list

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

* @param formular_list {list} 源算式列表

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

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

# 存储添加括号的算式
new_formular_list = []

# flag表示是否已存在左括号,作用在于构造出一对括号
flag = 0

# 添加括号
while(len(formular_list) > 1):
oper = formular_list.pop(1)
# 若下一个符号为 + or - , 则插入括号
if oper == '-' or oper == '+':
if flag == 0:
new_formular_list.append("(")
flag = 1
new_formular_list.append(formular_list.pop(0))
new_formular_list.append(oper)
else:
new_formular_list.append(formular_list.pop(0))

if flag == 1:
new_formular_list.append(")")
flag = 0

new_formular_list.append(oper)
# print(operand_list, operator_list, new_formular)

new_formular_list.append(formular_list.pop(0))
if flag == 1:
new_formular_list.append(")")

return new_formular_list

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

* @param formular_list {list} 源算式列表,可能包含括号

* @return {list}
'''

# 带入分数个数
fraction_num = 1
if self.opt.oper_num > 2:
fraction_num = (self.opt.oper_num - 1) / 2
index = random.randint(0, len(formular_list)-1)

interval = 1
while True:
if formular_list[index].isdigit():
break
elif formular_list[index - interval].isdigit():
index -= interval
break
elif formular_list[index + interval].isdigit():
index += interval
break
else:
interval += 1
formular_list[index] = self.getRandomFractionOperand()

return formular_list

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

* @return {list}
'''
# 生成原生算式
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_list):
'''
* 中缀表达式转为后缀表达式

* @param formular_list {list} 中缀表达式

* @return {list}
'''
# 运算符优先级
priority = {'×': 3, '÷': 3, '+': 2, '-': 2, '(': 1}

# 运算符栈
operator_stack = []

# 后缀表达式
post_formular_list = []

# 中缀表达式转为后缀表达式
while formular_list:
char = formular_list.pop(0)
if char == '(':
operator_stack.append(char)
elif char == ')':
oper_char = operator_stack.pop()
while oper_char != '(':
post_formular_list.append(oper_char)
oper_char = operator_stack.pop()
elif char in '+-×÷':
while operator_stack and priority[operator_stack[-1]] >= priority[char]:
post_formular_list.append(operator_stack.pop())
operator_stack.append(char)
else:
post_formular_list.append(char)

# 若符号栈不为空则循环
while operator_stack:
post_formular_list.append(operator_stack.pop())

# print(post_formular)
return post_formular_list

# @profile
def compute(self, char, num01, num02):
'''
* 计算算式的值

* @param char {str} 运算符

* @param num01 {str} 第二个数字,可能为分数

* @param num02 {str} 第二个数字,可能为分数

* @return {str}
'''
if char == '+':
return (Fraction(num02) + Fraction(num01)).__str__()
elif char == '-':
return (Fraction(num02) - Fraction(num01)).__str__()
elif char == '×':
return (Fraction(num02) * Fraction(num01)).__str__()
elif char == '÷':
try:
return (Fraction(num02) / Fraction(num01)).__str__()
except Exception as e:
# print("Error: ", e)
return "NaN"

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

* @param post_formular_list {list} 后缀表达式

* @return {str}
'''
# 操作数栈
operand_stack = []

while post_formular_list:
char = post_formular_list.pop(0)
if char in '+-×÷':
result = self.compute(char, operand_stack.pop(), operand_stack.pop())
if result == "NaN":
return result
operand_stack.append(result)
else:
operand_stack.append(char)

return operand_stack.pop()

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

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

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

return value

代码截图

psp下的四则运算

 

 

 psp下的四则运算

 

 

 psp下的四则运算

 

 

 本文代码借鉴一名作者(昵称:玩的三立方)的项目代码,

上一篇:C#实现一个简单计算器


下一篇:设计模式1——(简单工厂模式)