用python写了个计算器。可以实现对“+”,“-”,“*”,“/”以及括号的混合表达式的计算。
一开始在解析表达式时使用了两个递归,最后报运行时错误,提示递归深度不够,使用sys设置了下递归深度,还是不行,一旦设置太大就会出现内存错误,可能本人的机器太low了。后来把其中一个递归改成了循环,最终可以正常工作。
# coding:utf-8
# Author:李彪
# date:2016-03-20
#计算包含+、-、*、/以及多重括号的数字表达式:'-1-(2+(10-2*3)/(20-30/5))+(100-(4-300/6)-5*9/4+5)'
#没有对表达式中运算数进行非数字类型的判断---后期可添加
import re
import sys
import argparse
#设置递归深度
sys.setrecursionlimit(5000)
#这个类里面使用了递归,运行会提示递归深度不够,也许我的机器太low-----有兴趣的也许可以尝试下
class MyMaths():
def __init__(self):
pass
#计算表达式的值,并返回
def operatorParse(self,express):
# operators = {'+':self.addition,'-':self.subtraction,'*':self.multiplication,'/':self.division}
express = express.group()
**#这里的判定比较简单,么有做太多的考虑,肯定存在一定的问题**
if '+' in express:
return self.addition(express)
if '-' in express:
return self.subtraction(express)
if '*' in express:
return self.multiplication(express)
if '/' in express:
return self.division(express)
#加法运算
def addition(self,express):
first_data,second_data = express.split('+')
return str(float(first_data)+float(second_data))
#减法运算
def subtraction(self,express):
#判定第一个运算数为负数的情况
if express.startswith('-'):
first_data,second_data = express[1:].split('-',1)#减法运算时,仅使用‘-’split一次
first_data = '-' + first_data
else:
first_data,second_data = express.split('-',1)
return str(float(first_data)-float(second_data))
#乘法运算
def multiplication(self,express):
first_data,second_data = express.split('*')
return str(float(first_data)*float(second_data))
#除法运算
def division(self,express):
first_data,second_data = express.split('/')
return str(float(first_data)/float(second_data))
**#使用了递归,会出现运行时错误,提示递归深度超过**
def operator_priority(self,express):
pattern_1 = re.compile('(\-?\d+\.?\d*(\*|\/)+\-?\d+\.?\d*)')
pattern_2 = re.compile('(\-?\d+\.?\d*(\+|\-)+\-?\d+\.?\d*)')
if re.search(pattern_1,express):
express = re.sub(pattern_1,self.operatorParse,express)
return self.operator_priority(express)
elif re.search(pattern_2,express):
express = re.sub(pattern_2,self.operatorParse,express)
return self.operator_priority(express)
else:
return express
#计算表达式的值,并返回,使用内部方法
def operatorParse(express):
# operators = {'+':self.addition,'-':self.subtraction,'*':self.multiplication,'/':self.division}
#加法运算
def addition(express):
first_data,second_data = express.split('+')
return str(float(first_data)+float(second_data))
#减法运算
def subtraction(express):
#判定第一个运算数为负数的情况
if express.startswith('-'):
#减法运算时,仅使用‘-’split一次
first_data,second_data = express[1:].split('-',1)
first_data = '-' + first_data
else:
first_data,second_data = express.split('-',1)
return str(float(first_data)-float(second_data))
#乘法运算
def multiplication(express):
first_data,second_data = express.split('*')
return str(float(first_data)*float(second_data))
#除法运算
def division(express):
first_data,second_data = express.split('/')
return str(float(first_data)/float(second_data))
express = express.group()
**#这里的判定比较简单,么有做太多的考虑,肯定存在一定的问题**
if '+' in express:
return addition(express)
if '-' in express:
return subtraction(express)
if '*' in express:
return multiplication(express)
if '/' in express:
return division(express)
#express表达式中包含‘+’,‘-’,‘*’,‘/’运算符,operator_priority按照运算优先级进行运算
def operator_priority(express):
#首先通过循环首先来判断express中是否包含‘*’或者‘/’的表达式
pattern = re.compile('(\d+\.?\d*(\*|\/)+\-?\d+\.?\d*)')
while re.search(pattern,express):#re.search('(\*|\/)',express):
#如果express中包含乘法或者除法表达式,那么使用re.sub方法将符合正则条件的表达式提取并传给operatorParse
#用operatorParse返回值替换提取出来的表达式
#express指向完成替换操作的新的表达式,并再次循环判断
# print re.search(pattern,express).group()
express = re.sub(pattern,operatorParse,express)
#通过循环首先来判断express中是否包含‘+’或者‘-’的表达式
pattern = re.compile('(\-?\d+\.?\d*(\+|\-)+\d+\.?\d*)')
while re.search(pattern,express):#re.search('(\+|\-)',express):
#如果express中包含乘法或者除法表达式,那么使用re.sub方法将符合正则条件的表达式提取并传给operatorParse
#用operatorParse返回值替换提取出来的表达式
#express指向完成替换操作的新的表达式,并再次循环判断
express = re.sub(pattern,operatorParse,express)
return express
#以递归的方式从最里层将表达式中成对的带括号的表达式提取,作为参数传递给operator_priority方法
def parseBracket(srcStr):
# my_maths = MyMaths()
if '(' in srcStr or ')' in srcStr:
#查找第一个出现的‘)’的位置
first_Rbracket_pos = srcStr.find(')')
match_lbrocket_pos = None
for i in xrange(first_Rbracket_pos):
#根据第一个‘)’的下标往前搜索,直到找到最近的‘(’
if srcStr[first_Rbracket_pos - i] == '(':
match_lbrocket_pos = first_Rbracket_pos - i
break
else:
continue
#根据找到的‘(’和‘)’下标,截取带括号的表达式
sub_Expression = srcStr[match_lbrocket_pos:first_Rbracket_pos+1]
# print sub_Expression
#调用my_maths.operator_priority,该方法根据操作符优先级计算表达式的值并返回
retStr = operator_priority(sub_Expression.lstrip('(').rstrip(')'))
# print retStr
#用返回的值替换原表达式中提取的子表达式,生成新的表达式
newExpre = srcStr.replace(sub_Expression,retStr)
# print newExpre
#递归调用
return parseBracket(newExpre)
else:
#表达式中不再包含‘()’,此时直接将表达式传递到operator_priority进行运算,得到最终结果
retStr = operator_priority(srcStr)
return retStr
if __name__ == '__main__':
s = "-200-(1-(2+(10-2*3/2)/(20-30/5))+(100-(4-300/6)-5*9/4+5))"
print s + " = " + parseBracket(s)
程序测试运行,结果如下:
-200-(1-(2+(10-2*3/2)/(20-30/5))+(100-(4-300/6)-5*9/4+5)) = -338.25