Python实现简单的四则运算计算器
一、算法
1、算法的主要思想就是将一个中缀表达式(Infixexpression)转换成便于处理的后缀表达式(Postfixexpression),然后借助于栈这个简单的数据结构,计算出表达式的结果。
2、关于如何讲普通的表达式转换成后缀表达式,以及如何处理后缀表达式并计算出结果的具体算法描述不在此叙述了,书上有详细的说明。
二、简易计算器
使用说明
使用该计算器类的简单示例如下:
#usage
c=Calculator()
print('result:{:f}'.formart(c.get_result('1.11+2.22-3.33*4.44/5.55')))
#output:
result:0.666000
测试案例
为了对这个计算器进行有效地检验,设计了几组测试案例,测试结果如下:
TestNo.1:(1.11)=1.110000 TestNo.2:1.11+2.22-3.33*4.44/5.55=0.666000 TestNo.3:1.11+(2.22-3.33)*4.44/5.55=0.222000 TestNo.4:1.11+(2.22-3.33)*(4.44+5.55)/6.66=-0.555000 TestNo.5:1.11*((2.22-3.33)*(4.44+5.55))/(6.66+7.77)=-0.852992 TestNo.6:(1.11+2.22)*(3.33+4.44)/5.55*6.66=31.048920 TestNo.7:(1.11-2.22)/(3.33+4.44)/5.55*(6.66+7.77)/(8.88)=-0.041828 TestNo.8:Error:(1.11+2.22)*(3.33+4.44:missing")",pleasecheckyourexpression TestNo.9:Error:(1.11+2.22)*3.33/0+(34-45):divisorcannotbezero TestNo.10:Error:12+89^7:invalidcharacter:^
实现代码
栈的实现
栈实际上就是一个被限制操作的表,所有的操作只能在栈的顶端(入栈、出栈等),以下是使用Python代码实现的简单的栈:
classStack(object): """ ThestructureofaStack. Theuserdon'thavetoknowthedefinition. """ def__init__(self): self.__container=list() def__is_empty(self): """ Testifthestackisemptyornot :return:TrueorFalse """ returnlen(self.__container)==0 defpush(self,element): """ Addanewelementtothestack :paramelement:theelementyouwanttoadd :return:None """ self.__container.append(element) deftop(self): """ Getthetopelementofthestack :return:topelement """ ifself.__is_empty(): returnNone returnself.__container[-1] defpop(self): """ Removethetopelementofthestack :return:Noneorthetopelementofthestack """ returnNoneifself.__is_empty()elseself.__container.pop() defclear(self): """ We'llmakeanemptystack :return:self """ self.__container.clear() returnself
计算器类的实现
在计算器类中,我们将表达式的合法性验证单独放在一个函数中完成,但是实际上如果需要,也可以直接放在中缀表达式转后缀表达式的函数中实现,这样只需要一次遍历表达式即可同时完成验证和转换工作。但是为了保持结构清晰,还是分开来实现比较好,每个函数尽可能最好一件事情才是比较实在的。
在该计算器类中,有很多种极端的情况没有被考虑进去,因为那样的话整个实现的代码会更多。不过,可以在后期为整个类继续扩展,添加新的功能也是可以的。目前实现的就是主要框架,包括基本的错误检测和运算,重点时学习运用栈这个看似简单却强大的数据结构解决问题。
classCalculator(object):
"""
Asimplecalculator,justforfun
"""
def__init__(self):
self.__exp=''
def__validate(self):
"""
Wehavetomakesuretheexpressionislegal.
1.Weonlyacceptthe`()`tospecifythepriorityofasub-expression.Notes:`[{`and`]}`willbe
replacedby`(`and`)`respectively.
2.Validcharactersshouldbe`+`,`-`,`*`,`/`,`(`,`)`andnumbers(int,float)
-Invalidexpressionexamples,butwecanonlyhandlethe4thcase.Theimplementationwill
bemuchmoresophisticatedifwewanttohandleallthepossiblecases.:
1.`a+b-+c`
2.`a+b+-`
3.`a+(b+c`
4.`a+(+b-)`
5.etc
:return:TrueorFalse
"""
ifnotisinstance(self.__exp,str):
print('Error:{}:expressionshouldbeastring'.format(self.__exp))
returnFalse
#Savethenon-spaceexpression
val_exp=''
s=Stack()
forxinself.__exp:
#Weshouldignorethespacecharacters
ifx=='':
continue
ifself.__is_bracket(x)orself.__is_digit(x)orself.__is_operators(x)\
orx=='.':
ifx=='(':
s.push(x)
elifx==')':
s.pop()
val_exp+=x
else:
print('Error:{}:invalidcharacter:{}'.format(self.__exp,x))
returnFalse
ifs.top():
print('Error:{}:missing")",pleasecheckyourexpression'.format(self.__exp))
returnFalse
self.__exp=val_exp
returnTrue
def__convert2postfix_exp(self):
"""
Converttheinfixexpressiontoapostfixexpression
:return:theconvertedexpression
"""
#highestpriority:()
#middle:*/
#lowest:+-
converted_exp=''
stk=Stack()
forxinself.__exp:
ifself.__is_digit(x)orx=='.':
converted_exp+=x
elifself.__is_operators(x):
converted_exp+=''
tp=stk.top()
iftp:
iftp=='(':
stk.push(x)
continue
x_pri=self.__get_priority(x)
tp_pri=self.__get_priority(tp)
ifx_pri>tp_pri:
stk.push(x)
elifx_pri==tp_pri:
converted_exp+=stk.pop()+''
stk.push(x)
else:
whilestk.top():
ifself.__get_priority(stk.top())!=x_pri:
converted_exp+=stk.pop()+''
else:
break
stk.push(x)
else:
stk.push(x)
elifself.__is_bracket(x):
converted_exp+=''
ifx=='(':
stk.push(x)
else:
whilestk.top()andstk.top()!='(':
converted_exp+=stk.pop()+''
stk.pop()
#popalltheoperators
whilestk.top():
converted_exp+=''+stk.pop()+''
returnconverted_exp
def__get_result(self,operand_2,operand_1,operator):
ifoperator=='+':
returnoperand_1+operand_2
elifoperator=='-':
returnoperand_1-operand_2
elifoperator=='*':
returnoperand_1*operand_2
elifoperator=='/':
ifoperand_2!=0:
returnoperand_1/operand_2
else:
print('Error:{}:divisorcannotbezero'.format(self.__exp))
returnNone
def__calc_postfix_exp(self,exp):
"""
Gettheresultfromaconvertedpostfixexpression
e.g.6523+8*+3+*
:return:result
"""
assertisinstance(exp,str)
stk=Stack()
exp_split=exp.strip().split()
forxinexp_split:
ifself.__is_operators(x):
#poptwotopnumbersinthestack
r=self.__get_result(stk.pop(),stk.pop(),x)
ifrisNone:
returnNone
else:
stk.push(r)
else:
#pushtheconvertednumbertothestack
stk.push(float(x))
returnstk.pop()
def__calc(self):
"""
Trytogettheresultoftheexpression
:return:Noneorresult
"""
#Validate
ifself.__validate():
#Convert,thenrunthealgorithmtogettheresult
returnself.__calc_postfix_exp(self.__convert2postfix_exp())
else:
returnNone
defget_result(self,expression):
"""
Gettheresultofanexpression
Supposewehavegotavalidexpression
:return:Noneorresult
"""
self.__exp=expression.strip()
returnself.__calc()
"""
Utilities
"""
@staticmethod
def__is_operators(x):
returnxin['+','-','*','/']
@staticmethod
def__is_bracket(x):
returnxin['(',')']
@staticmethod
def__is_digit(x):
returnx.isdigit()
@staticmethod
def__get_priority(op):
ifopin['+','-']:
return0
elifopin['*','/']:
return1
总结
以上就是利用Python实现简单四则运算计算器的全部内容,希望本文的内容对大家的学习或者工作能有所帮助,如果有疑问大家可以留言交流。
参考
《数据结构与算法(C语言)》上相关章节算法描述