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语言)》上相关章节算法描述