python 实现四则运算(一)

来源:互联网 发布:域名服务器ip查询 编辑:程序博客网 时间:2024/06/05 02:03


为了学习python,前段时间从网上看到一个题目(百练题号4132),求解输入的四则运算式。输入是一个包含加、减、乘、除四则运算式,输出计算结果,取小数点后两位。


一、实现思路

1. 从键盘读取四则运算式,这里读的是一个字符串S。

2. 将字符串S划分为单个的运算符和运算数。这里把加“+”、减“-”、乘“*”、除“/”称为运算符,数字称为运算数,运算数可以为整数、小数。

3. 将划分出的运算符和运算数,按照原来的顺序,重新组成一个列表tokenlist。

4. 对元组列表tokenlist,按照从左到右的顺序依次进行处理。

  • 处理过程中用到几个数据:两个栈:numStack,用于存储操作数;opStack,用来存储操作符;一个ops列表,保存了6种运算符:+、-、*、/、(、)。一个opps字典,保存了运算符优先级。
  • 如果tokenlist[i] 不是操作符,就将其压入numStack,否则,压入opStack。虽然根据numStack和opStack的状态分别作出相应的处理。主要处理过程放在压入numStack之后。

二、函数介绍

代码中定义并实现了几个函数。其中:

  • main()        主函数。
  • delSpace() 删除输入串中间夹杂的空格符号(目前是多余的)。
  • toDigitl()     将输入串中的运算数从字符型转换成数值型(有整数、有浮点数)。
  • tokenlist()   将输入串划分成单个的运算符和运算数。这里的关键是处理小数点和最后面的括号。识别运算符的方法就是查找运算符列表,如果在ops中则认为是。识别运算数的方法,是用两个变量分别代别一个运算数的开始位置和结束位置,用这两个代表位置的变量,对输入串进行切片。
  • caculate(tokenlist)   是主要计算函数,参数为处理过的输入串,返回结果。在写caculate()的过程中,对重复出现和影响代码理解的部分进行了改写,结果就多出了两个函数:fourRules() 、xcacul()

三、源码

# Caculate four fundamental rules expressionimport iofrom collections import dequeimport timedef delSpace(s):"""Delete blank space in String"""s1 = ''for a in s:# if a is blank space, if a != ' ':s1 += areturn s1def toDigitl(sl):"""INPUT:['1','+','2.3','+','4'] OUTPT:[1,'+',2.3,'+',4]"""d = []sign = ['+','-','*','/','(',')']for s in sl:if (s in sign):d.append(s)elif s.isnumeric():d.append(int(s))else:d.append(float(s))return ddef tokenList(s):"""e.g. s = '1+2+4' , return ['1','+','2','+','4']"""t1 = []sp = ''sign = ['+','-','*','/','(',')']j, k = 1, 0for i in range(len(s)):if s[i] in sign:if s[i-1] in sign:sp = s[k:k+j]j += 1else:t1.append(sp)t1.append(s[i])j = 1k = i + 1else:sp = s[k:k+j]j += 1# process last charif i == len(s)-1:t1.append(sp)# pop right bracketif i == len(s)-1 and s[i] in sign:t1.pop()return t1def fourRules(a,b,s):    if s == '+': return a+b    if s == '-': return a-b    if s == '*': return a*b    if s == '/': return a/bdef xcacu(ns,sg):   b1 = ns.pop()   a1 = ns.pop()   r = fourRules(a1,b1,sg)   ns.append(r)     def caculate(tokenlist):    numStack = deque()     opStack = deque()    ops = ['+','-','*','/','(',')']    opps = {'+':0,'-':0,'*':1,'/':1,'(':2,')':2}    opCurrent = ''      for i in range(len(tokenlist)):        if tokenlist[i] in ops:            opStack.append(tokenlist[i])        else:            numStack.append(tokenlist[i])            if i<len(tokenlist)-1 and len(numStack) >= 2 and len(opStack) >= 1:                opCurrent = opStack.pop()                if opps[tokenlist[i+1]] <= opps[opCurrent]:                    xcacu(numStack,opCurrent)                else:                    opStack.append(opCurrent)                if i == len(tokenlist)-1:                    xcacu(numStack,opCurrent)    # print(i,numStack,opStack)     while(len(opStack) > 0):       xcacu(numStack,opStack.pop())    return numStack.pop()def main():     s = input()    while s != 'q':                starttime = time.time()                 tt = toDigitl(tokenList(delSpace(s)))        print('%s is %.2f.'%(s,caculate(tt)))                  endtime =  time.time() - starttime        print('RUN TIME:%.10f ms'%(endtime*1000))                 s = input()if __name__=='__main__':    main()

四、运行结果



五、后续工作

看到有人用二叉树来存储运算式,笔者在这里只是用python自带的collections库中的deque来模拟栈。这里运算符中虽然写了左右括号,但现在还未实现,仅完成不带括号情况下的四则计算部分。带括号部分,写好后再贴出来。



0 0