標籤:python 演算法 計算機 運算式
概述: 如何運行一個運算式,例如:12+23*4/2這個我想大家都很瞭解。不過,如果這個運算式是一個字串呢?或是這樣來描述,一個運算式被寫成了一個字串,我們又應該如何去運行並求得值呢?你是否會想,如果我們能夠拿到12, 23, 4, 2以及中間的運算子,那就是真的太好了。而事實上,我們也正是在朝著這個方向去努力。如果你學過演算法或是資料結構,那我想這個小問題便不會阻止你前進了。
思路分析: 如概述所說,如果我們能拿到字串運算式中中各個我們肉眼能夠識別的“元素”,就算我們邁過了第一步。什麼!才第一步?是的,這才是第一步。那第二步是什嗎?
沒錯,第二步就是運算。運算的過程會有一個難題,這個難題就是操作符的優先順序問題,就拿上面的運算式來說,我們需要先進行23*4的運算,而不是12+23的運算。我們要做的就是讓電腦按照我們認知中的優先來做運算。比較笨的方法就是依次遍曆兩遍運算式(事實上在後期的運算中,我們遍曆的是一個列表)。第一遍先做乘除、第二遍再做加減。
元素分離: 對於這一步操作在Python中進行的確很省事,因為我們可愛的
Python可以在列表中儲存不同類型的對象。這就有點像C中的結構體和Java中的類。我們首先得到的是一個個的字元,再對這些字元進行遍曆和分類(是數字還是操作符)。
# split expressiondef mixed_operation (exp): exp_list = list(exp) temp = '' behavor_list = [] i = 0 length = len(exp_list) for item in exp_list: if is_operation(item): behavor_list.append(int(temp)) behavor_list.append(item) temp = '' else: temp += item if i == length - 1: behavor_list.append(int(temp)) break; i += 1 return behavor_list
邏輯運算: 這個函數有一些特別,對於有編程經驗的朋友可能已經不陌生。對,就是
遞迴!對於一個coder,遞迴是必須掌握的,就讓我們一起在合適的時候把遞迴搞起吧。這裡寫遞迴的原因就是我們的運算式中每一種運算子不可能只有一種。我們要一直這樣遍曆下去。這時可能你已經感覺到了,遍曆的話,為什麼不用for?是的,在My Code裡也有for的迴圈代碼,不過這裡的for可沒有想像中那麼好用,不信你可以試試看。
# Calculation op1 and op2('*' and '/' or '+' and '-')def cal_op1_op2(exp_list, op1, op2): if len(exp_list) == 1: return exp_list i = 0 has_op = False for i in range(2, len(exp_list), 2): a = exp_list[i - 2] o = exp_list[i - 1] b = exp_list[i] if o == op1 or o == op2: has_op = True exp_list[i - 2] = get_aob(a, o, b) del exp_list[i] del exp_list[i - 1] break if has_op == False: return exp_list return cal_op1_op2(exp_list, op1, op2)
特別說明: 當然對於這個程式來說,並不是那麼健壯。因為我們這些邏輯的前提是我們得到了一個正常的運算式,且不包含括弧。所謂正常運算式,就是不會出現少數字或是少操作符或是輸入了非‘+‘、‘-‘、‘*‘、‘/‘、[0-9]的字元或是字元集。我們的程式預設了一個理想的運行環境,因為只是說明代碼的思路。
附完整代碼:
#!/usr/bin/env python'expression_cal.py -- cal the expression that you give to me'# judgment a char is a operation or notdef is_operation(oper): if oper == '+' or oper == '-' or oper == '*' or oper == '/': return True else: return False# split expressiondef mixed_operation (exp): exp_list = list(exp) temp = '' behavor_list = [] i = 0 length = len(exp_list) for item in exp_list: if is_operation(item): behavor_list.append(int(temp)) behavor_list.append(item) temp = '' else: temp += item if i == length - 1: behavor_list.append(int(temp)) break; i += 1 return behavor_list# cal a o bdef get_aob(a, o, b): if o == '+': return a + b elif o == '-': return a - b elif o == '*': return a * b elif o == '/': return a / b# Calculation op1 and op2('*' and '/' or '+' and '-')def cal_op1_op2(exp_list, op1, op2): if len(exp_list) == 1: return exp_list i = 0 has_op = False for i in range(2, len(exp_list), 2): a = exp_list[i - 2] o = exp_list[i - 1] b = exp_list[i] if o == op1 or o == op2: has_op = True exp_list[i - 2] = get_aob(a, o, b) del exp_list[i] del exp_list[i - 1] break if has_op == False: return exp_list return cal_op1_op2(exp_list, op1, op2)# cal expdef cal_exp(exp_list): exp_list = cal_op1_op2(exp_list, '*', '/') exp_list = cal_op1_op2(exp_list, '+', '-') return exp_list[0]while True: expre = raw_input('Enter your expression(0 to end):\n') if expre == '0': break result = mixed_operation(expre) print 'list result = ', print result print cal_exp(result)print 'END'
使用Python運算一個字串運算式