#!/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()