练习python写了一个四则运算程序,支持乘方和“.3"这种格式
2017-01-05 13:48
363 查看
#!/usr/bin/python
#coding=utf-8
# 本程序由用户输入一个表达式字符串,然后计算这个表达式的值
# 表达式是一个四则运算表达式,可以包含^操作符
# 注意:乘方用^运算符,支持".3"这种表示小数的形式。负数需要用括号扩起来
# 思路:利用栈的方法,先将表达式从中缀表达式转换成后缀表达式,再进行计算
def isNum(value):
try:
value+1
except TypeError:
return False
else:
return True
def cal(strexpp):
''' 本函数由一个四则运算表达式字符串计算表达式的值
strexpr为一个四则运算表达式,如果这个表达式正确,则函数返回这个表达式的值,否则返回NULL'''
seqLegalChar=('+','-','*','/','(',')','^','1','2','3','4','5','6','7','8','9','0','.') #表达式中合法的字符集
seqOpr=seqLegalChar[0:7] #运算符序列
seqOpa=seqLegalChar[7:18] #操作数序列
# 表达式为空,则返回Null
if len(strexpp)==0: return Null
#去掉字符串中的空格
strexpr=strexpp.replace(' ','')
# 表达式包含不合法的支付,则返回Null
for ch in strexpr:
if ch not in seqLegalChar:
return Null
# 将表达式变成一个数字和符号的序列
numstart=-1 #标识数字的起始位置为numstart+1
seqExpr=[] #表达式序列
for i in range(0,len(strexpr)): #将表达式的数字和符号依次输出到序列
#本位置指向的是一个操作数,
if (strexpr[i] in seqOpa):
if numstart<0: #如果numstart小于0,使numstart指向本位置数字开始的地方
numstart=i
if i==len(strexpr)-1: #已读取到表达式最后一个字符,将数字转换后入列
seqExpr.append(float(strexpr[numstart:len(strexpp)]))
continue
#本次读取的字符是一个符号
if numstart>=0: #如果numstart大于0,则说明numstart与本位置之间是数字,需要提取数字。如果numstart==-1,则表明中间都是符号
seqExpr.append(float(strexpr[numstart:i])) #中间是数字,将数字转换后输出到序列
seqExpr.append(strexpr[i]) #将本次符号输出到序列
numstart=-1 #将numstart指针修改为本次位置
#将中缀表达式转换成为后缀表达式
seqPosfix=[] #后缀表达式序列,完成后seqPosfix中即为后缀表达式
stkOpra=[] #转换中所需要的符号栈
for op in seqExpr:
if isNum(op): #如果是数字,则直接输出到后缀表达式序列
seqPosfix.append(op)
continue
if not stkOpra: #如果符号栈为空,则直接压入第一个符号
stkOpra.append(op)
continue
if op ==')': #如果是')',需要匹配以前的'(',栈顶元素依次出栈输出,知道'('为止
while stkOpra[len(stkOpra)-1]!='(':
seqPosfix.append(stkOpra.pop()) #将'('弹出
stkOpra.pop()
elif op in ['+','-']: #如果是'+'或者'-',优先级最低
while (stkOpra and (stkOpra[len(stkOpra)-1]!='(')):
seqPosfix.append(stkOpra.pop())
stkOpra.append(op)
elif op in ['*','/']: #如果是'*','/',栈顶是'*','/','^'则弹出,否则入栈
while (stkOpra and (stkOpra[len(stkOpra)-1]=='^' )):
seqPosfix.append(stkOpra.pop())
stkOpra.append(op)
elif op in ['^','(']: #如果是'^'和'(',优先级最高,则直接入栈
stkOpra.append(op)
while stkOpra: #到最后如果符号栈不为空,则将符号栈的符号全部出栈
seqPosfix.append(stkOpra.pop())
#根据后缀表达式seqPosfix计算值
stkNumb=[] #装载操作数和值的栈
for op in seqPosfix:
if isNum(op):
stkNumb.append(op) #如果是数字,直接进栈
continue
p1=stkNumb.pop() #弹出两个操作数
p2=stkNumb.pop()
if op=='^': #根据运算符计算操作数的值
p=p2**p1
elif op=='*':
p=p2*p1
elif op=='/':
p=p2/p1
elif op=='+':
p=p2+p1
elif op=='-':
p=p2-p1
stkNumb.append(p) #将计算结果入栈
return stkNumb.pop() #最后的结果
expr=raw_input("请输入一个四则运算表达式(负数需要用括号扩起来,乘方用'^'运算符):")
res=cal(expr)
if not res:
print "你输入的四则运算表达式包含有不正确的字符,请检查后重新输入。"
else:
print "结果为:%f" % res
#coding=utf-8
# 本程序由用户输入一个表达式字符串,然后计算这个表达式的值
# 表达式是一个四则运算表达式,可以包含^操作符
# 注意:乘方用^运算符,支持".3"这种表示小数的形式。负数需要用括号扩起来
# 思路:利用栈的方法,先将表达式从中缀表达式转换成后缀表达式,再进行计算
def isNum(value):
try:
value+1
except TypeError:
return False
else:
return True
def cal(strexpp):
''' 本函数由一个四则运算表达式字符串计算表达式的值
strexpr为一个四则运算表达式,如果这个表达式正确,则函数返回这个表达式的值,否则返回NULL'''
seqLegalChar=('+','-','*','/','(',')','^','1','2','3','4','5','6','7','8','9','0','.') #表达式中合法的字符集
seqOpr=seqLegalChar[0:7] #运算符序列
seqOpa=seqLegalChar[7:18] #操作数序列
# 表达式为空,则返回Null
if len(strexpp)==0: return Null
#去掉字符串中的空格
strexpr=strexpp.replace(' ','')
# 表达式包含不合法的支付,则返回Null
for ch in strexpr:
if ch not in seqLegalChar:
return Null
# 将表达式变成一个数字和符号的序列
numstart=-1 #标识数字的起始位置为numstart+1
seqExpr=[] #表达式序列
for i in range(0,len(strexpr)): #将表达式的数字和符号依次输出到序列
#本位置指向的是一个操作数,
if (strexpr[i] in seqOpa):
if numstart<0: #如果numstart小于0,使numstart指向本位置数字开始的地方
numstart=i
if i==len(strexpr)-1: #已读取到表达式最后一个字符,将数字转换后入列
seqExpr.append(float(strexpr[numstart:len(strexpp)]))
continue
#本次读取的字符是一个符号
if numstart>=0: #如果numstart大于0,则说明numstart与本位置之间是数字,需要提取数字。如果numstart==-1,则表明中间都是符号
seqExpr.append(float(strexpr[numstart:i])) #中间是数字,将数字转换后输出到序列
seqExpr.append(strexpr[i]) #将本次符号输出到序列
numstart=-1 #将numstart指针修改为本次位置
#将中缀表达式转换成为后缀表达式
seqPosfix=[] #后缀表达式序列,完成后seqPosfix中即为后缀表达式
stkOpra=[] #转换中所需要的符号栈
for op in seqExpr:
if isNum(op): #如果是数字,则直接输出到后缀表达式序列
seqPosfix.append(op)
continue
if not stkOpra: #如果符号栈为空,则直接压入第一个符号
stkOpra.append(op)
continue
if op ==')': #如果是')',需要匹配以前的'(',栈顶元素依次出栈输出,知道'('为止
while stkOpra[len(stkOpra)-1]!='(':
seqPosfix.append(stkOpra.pop()) #将'('弹出
stkOpra.pop()
elif op in ['+','-']: #如果是'+'或者'-',优先级最低
while (stkOpra and (stkOpra[len(stkOpra)-1]!='(')):
seqPosfix.append(stkOpra.pop())
stkOpra.append(op)
elif op in ['*','/']: #如果是'*','/',栈顶是'*','/','^'则弹出,否则入栈
while (stkOpra and (stkOpra[len(stkOpra)-1]=='^' )):
seqPosfix.append(stkOpra.pop())
stkOpra.append(op)
elif op in ['^','(']: #如果是'^'和'(',优先级最高,则直接入栈
stkOpra.append(op)
while stkOpra: #到最后如果符号栈不为空,则将符号栈的符号全部出栈
seqPosfix.append(stkOpra.pop())
#根据后缀表达式seqPosfix计算值
stkNumb=[] #装载操作数和值的栈
for op in seqPosfix:
if isNum(op):
stkNumb.append(op) #如果是数字,直接进栈
continue
p1=stkNumb.pop() #弹出两个操作数
p2=stkNumb.pop()
if op=='^': #根据运算符计算操作数的值
p=p2**p1
elif op=='*':
p=p2*p1
elif op=='/':
p=p2/p1
elif op=='+':
p=p2+p1
elif op=='-':
p=p2-p1
stkNumb.append(p) #将计算结果入栈
return stkNumb.pop() #最后的结果
expr=raw_input("请输入一个四则运算表达式(负数需要用括号扩起来,乘方用'^'运算符):")
res=cal(expr)
if not res:
print "你输入的四则运算表达式包含有不正确的字符,请检查后重新输入。"
else:
print "结果为:%f" % res
相关文章推荐
- 关于出现错误:_tkinter.TclError: couldn't open "E:\Python系列\Python程序\Python安装.gif"tkinter中不能打开GIF格式图片的解决办法
- python练习程序(运算,math,格式化)
- python小练习七——支持多用户在线的FTP程序
- 解决Hibernate 3不支持 "&" 运算的SQL语句
- [数据库测试]强烈推荐一个python ODBC数据源插件,可支持Oracle,Db2,Mysql,Sql-server以及各种数据库版本,附例子和测试程序
- python练习程序(下载网页)
- 解决"未能加载文件或程序集,或它的某一个依赖项,试图加载格式不正确的程序"问题一法
- 计算器程序,支持+-*/和(),以#号结尾,有词法分析,和运算,没有语法分析是否正确,但是只要输入正确就能运行
- 用1、2、3、3、4、5这六个数字,用java写一个程序,打印出所有不同的排列 要求:"4"不能在第三位,"3"与"5"不能相连。
- Java程序练习-长整数加法运算
- python练习程序(获取系统当前时间)
- [数据库测试]强烈推荐一个python ODBC数据源插件,可支持Oracle,Db2,Mysql,Sql-server以及各种数据库版本,附例子和测试程序
- Windows XP 更新程序 (KB955704) 添加对exFAT文件系统格式的支持
- 支持MSNP15的MSN登录程序PYTHON版代码
- python简明教程练习--命令行 地址簿 程序
- 解决Hibernate 3不支持 "&" 运算的SQL语句
- [数据库测试]强烈推荐一个python ODBC数据源插件,可支持Oracle,Db2,Mysql,Sql-server以及各种数据库版本,附例子和测试程序
- VC / MFC 程序出现 "试图执行系统不支持的操作"
- 用Ruby给小宝做的数学算术口算练习程序(带四则运算的!)
- 用Python给小宝做的数学四则运算_算术口算练习程序(后添加减乘除)