python 實現四則運算 無優先級 VS 有優先級

#!/usr/bin/env python
#coding=utf-8
#實現加減乘除-無優先級,從左至右計算
def split_str(str):
     L = []
     s_index = 0 #上次切割的索引
     i = 0 #遍歷時當前的索引
     #print str
     for s in str:
                if s in '+-*/': #遇到運算符開始執行切割
                              L.append(str[s_index:i]) #寫入list
     #                       print "str[s_index:i]: ",str[s_index:i]
                              s_index = i #上次切割索引前移
     #                       print "s_index :", s_index
                i += 1 # 非運算符索引前移
     #               print 'i: ',i
     L.append(str[s_index:])#切割後最後一部分寫入list
     init_value = L[0] #list第一個值無需計算,設爲初始值
     for num in range(1,len(L)):
                init_value = calculate_list(init_value,L[num]) #計算結果賦值給初始值,即左操作數
     return init_value

def calculate_list(a,b):
        return operate_map[b[0]](int(a),int(b[1:]))
#定義詞典 + - * / 符號爲key,value爲運算結果
operate_map = {
     '+' : lambda x,y : x+y,
     '-' : lambda x,y : x-y,
     '*' : lambda x,y : x*y,
     '/' : lambda x,y : x/y
}

if __name__ == '__main__':
     cal_str = "8/2+10+2*3-14"
     cal_list = split_str(cal_str)
     print cal_list

以上爲$ cat calculate1.py

利用上面的的規則實現優先級:

#!/usr/bin/env python
#coding=utf-8
from calculate1 import *
#實現加減乘除 -- 有優先級 ,先 * / 後 + -
def _split_str(str):
     L = []
     s_index = 0 #上次切割的索引
     i = 0 #遍歷時當前的索引
     print str
     for s in str:
        if s in '-+': #遇到+-運算符開始執行切割
                L.append(str[s_index:i]) #寫入list
                L.append(s) #寫入list
                s_index = i+1 #上次切割索引前移
        i += 1 # 非運算符索引前移
     L.append(str[s_index:])#切割後最後一部分寫入list
     return L
#cal_str = "12+11/13*1-5*9"
cal_str = raw_input("Enter an arithmetic express:")
cal_list = _split_str(cal_str)
#['12', '+', '11/13*1', '-', '5*9']

s=''
for i in cal_list:
     if "*" in i or '/' in i:
        s=s+str(split_str(i))
     else:
        s=s+str(i)
print split_str(s)

另外在Stackoverflow上看到的後綴四則運算的代碼,記錄下:

#The question I'm having problem on is calculating the postfix form expressions: for example, (1, 2, '+', 3, '*').
#http://stackoverflow.com/questions/22579121/stack-calculator-postfix-python/22585579#22585579
import sys
if sys.hexversion < 0x3000000:
    # Python 2.x
    is_str = lambda s: isinstance(s, basestring)
    inp = raw_input
else:
    # Python 3.x
    is_str = lambda s: isinstance(s, str)
    inp = input
class Stack(list):
    def pop_n(self, n):
        """
        Pop n items off stack, return as list
        """
        assert n >= 0, "Bad value {}: n cannot be negative".format(n)
        if n == 0:
            return []
        elif n <= len(self):
            res = self[-n:]
            del self[-n:]
            print "Stack pop_n res:", res
            return res
        else:
            raise ValueError("cannot pop {} items, only {} in stack".format(n, len(self)))

    def push_n(self, n, items):
        """
        Push n items onto stack
        """
        assert n == len(items), "Expected {} items, received {}".format(n, len(items))
        self.extend(items)
        print "Stack push_n self: ", self
class Op:
    def __init__(self, num_in, num_out, fn):
        """
        A postfix operator

        num_in:     int
        num_out:    int
        fn:         accept num_in positional arguments,
                    perform operation,
                    return list containing num_out values
        """
        assert num_in  >= 0, "Operator cannot have negative number of arguments"
        self.num_in = num_in
        assert num_out >= 0, "Operator cannot return negative number of results"
        self.num_out = num_out
        self.fn = fn

    def __call__(self, stack):
        """
        Run operator against stack (in-place)
        """
        args = stack.pop_n(self.num_in)         # pop num_in arguments
        print "Op args: ",args
        res = self.fn(*args)                    # pass to function, get results
        print "Op res: ",res
        stack.push_n(self.num_out, res)         # push num_out values back
        print "Op stack", stack
ops = {
    '*':  Op(2, 1, lambda a,b: [a*b]),          # multiplication
    '/':  Op(2, 1, lambda a,b: [a//b]),         # integer division
    '+':  Op(2, 1, lambda a,b: [a+b]),          # addition
    '-':  Op(2, 1, lambda a,b: [a-b]),          # subtraction
    '/%': Op(2, 2, lambda a,b: [a//b, a%b])     # divmod (example of 2-output op)
}
def postfix_eval(tokens):
    """
    Evaluate a series of tokens as a postfix expression;
    return the resulting stack
    """
    if is_str(tokens):
        # if tokens is a string, treat it as a space-separated list of tokens
        tokens = tokens.split()

    stack = Stack()
    for token in tokens:
        try:
            # Convert to int and push on stack
            stack.append(int(token))
            print "postfix_eval stack :", stack
        except ValueError:
            try:
                # Not an int - must be an operator
                # Get the appropriate operator and run it against the stack
                op = ops[token]
                print "postfix_eval op:", op
                #op(stack)         # runs Op.__call__(op, stack)
                print "token:",token
                print "postfix_eval op(stack)", op(stack) 
            except KeyError:
                # Not a valid operator either
                raise ValueError("unknown operator {}".format(token))
    return stack
def main():
    while True:
        expr = inp('\nEnter a postfix expression (or nothing to quit): ').strip()
        if expr:
            try:
                print("  => {}".format(postfix_eval(expr)))
            except ValueError as error:
                print("Your expression caused an error: {}".format(error))
        else:
            break

if __name__=="__main__":
    main()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章