python實現計算器
參考
https://blog.csdn.net/a971956955/article/details/81489914
https://www.cnblogs.com/dbefb/p/12346648.html
https://next.xuetangx.com/learn/THU08091000367/THU08091000367/1516221/exercise/1385889
1.題目描述
實現一個計算器的控制台程序,支持加減乘除、乘方、括號、小數點,運算符優先級為括號>乘方>乘除>加減,同級別運算按照從左向右的順序計算
1.1輸入描述
- 數字包括"0123456789",小數點為".",運算符包括:加("+")、減("-")、乘("*")、除("/")、乘方("^",注:不是**!)、括號("()")
- 需要從命令行參數讀入輸入,例如提交文件為main.py,可以用python3 main.py "1+2-3+4"的方式進行調用,Java程序也是類似的,如果你的程序需要通過鍵盤輸入,那么是不符合要求的,例如python使用input()來等待用戶輸入,這會因為自動評測時不會有用戶輸入所以不會有任何結果
- 輸入需要支持空格,即 python3 main.py "1 + 2 - 3 + 4" 也需要程序能夠正確給出結果,Java程序也是類似的
- 所有測試用例中參與運算的非零運算數的絕對值范圍保證在 109-10(-10) 之內, 應該輸出運算結果時非零運算結果絕對值也保證在該范圍內
1.2輸出描述
- 數字需要支持小數點,輸出結果取10位有效數字,有效數字位數不足時不能補0
- 對於不在輸入描述內的輸入,輸出INPUT ERROR
- 對於格式不合法(例如括號不匹配等)的輸入,輸出 FORMAT ERROR
- 對於不符合運算符接收的參數范圍(例如除0等)的輸入,輸出VALUE ERROR
- 對於2、3、4的情況,輸出即可,不能拋出異常
- 同時滿足2、3、4中多個條件時,以序號小的為准
1.3樣例
輸入: 1 + 2 - 3 + 4
輸出: 4
輸入: 1 + 2 - 3 + 1 / 3
輸出: 0.3333333333
輸入: 1 + + 2
輸出: FORMAT ERROR
輸入: 1 / 0
輸出: VALUE ERROR
輸入: a + 1
輸出: INPUT ERROR
2.解決方案
2.1思路
- 需要格外注意括號,實現運算符的優先級實現
- 當一個表達式中不含括號的時候是比較好處理的,所以要想辦法去掉括號。一個方法是先計算括號內的表達式,然后用計算結果代替這個括號
- 首先將數字和運算符提取到列表保存,然后對列表中元素逐一處理
- 去括號:遞歸的去除最內層的括號
- 去加減乘除號:依次處理
2.2表達式轉變成列表
關於正則表達式請見我的隨筆正則表達式
def equation_to_list(equation):
equation_list = re.findall(r"[\d\.]+|\(|\+|\-|\*|\/|\)+", equation)
return equation_list
equation = "(5.4+3.6/3)*1.0"
print(equation_to_list(equation))
# ['(', '5.4', '+', '3.6', '/', '3', ')', '*', '1.0']
2.3完整代碼
import re
import sys
def conversionFormula(formula):
format_list = re.findall('[\w\.]+|\(|\+|\-|\*|\/|\^|\)', formula)
switch = 0
switch2 = 0
count = 0
for i in format_list:
if i == '(' or i == ')': # 進行括號符號的判斷
switch2 += 1
for i in format_list:
if i == '+' or i == '-' or i == '*' or i == '/' or i == '^': # 進行加減乘除乘方符號的判斷
switch = 1
break
if switch != 1:
print('INPUT ERROR')
return 'ERROR'
for i in format_list: # 進行一些錯誤的判斷
if i == '+' or i == '-' or i == '*' or i == '/':
if format_list[count - 1] == '+' or format_list[count - 1] == '-' or \
format_list[count - 1] == '*' or format_list[count - 1] == '/' or \
format_list[count + 1] == '+' or format_list[count + 1] == '-' or \
format_list[count + 1] == '*' or format_list[count + 1] == '/':
print('FORMAT ERROR')
return 'ERROR'
elif i == '/' and format_list[count + 1] == '0':
print('VALUE ERROR')
return 'ERROR'
elif i.isalpha():
print('INPUT ERROR')
return 'ERROR'
count += 1
if switch2 % 2 != 0:
print('FORMAT ERROR')
return 'ERROR'
return format_list
def remove_bracket(formula):
leftBracket = 0
count = 0 # 用遍歷列表進行計數
for i in formula:
if i == '(': # 記錄最內側左括號的位置
leftBracket = count
elif i == ')':
smallestFomula = formula[leftBracket + 1:count] # 提取最內層括號里式子
smallestFomulaAnswer = calculator(smallestFomula) # 調用calculator方法進行計算
if smallestFomulaAnswer < 0: # 更新式子,對去括號后的+-,--情況進行分析
if formula[leftBracket - 1] == '-':
formula[leftBracket - 1] = '+'
temp = formula[:leftBracket]
temp.append(str(abs(smallestFomulaAnswer)))
formula = temp + formula[count + 1:]
elif formula[leftBracket - 1] == '+':
formula[leftBracket - 1] = '-'
temp = formula[:leftBracket]
temp.append(str(abs(smallestFomulaAnswer)))
formula = temp + formula[count + 1:]
else:
temp = formula[:leftBracket]
temp.append(str(smallestFomulaAnswer))
formula = temp + formula[count + 1:]
else:
temp = formula[:leftBracket]
temp.append(str(smallestFomulaAnswer))
formula = temp + formula[count + 1:]
return remove_bracket(formula) # 遞歸,進行新式子的去括號分析
count += 1
return formula # 返回無括號的最終式子
def calculator(formula):
count = 0
for i in formula: # 先處理乘方、乘除
if i == '^':
formula[count - 1] = str(float(formula[count - 1]) ** float(formula[count + 1]))
del (formula[count])
del (formula[count])
return calculator(formula)
elif i == '*':
formula[count - 1] = str(float(formula[count - 1]) * float(formula[count + 1]))
del (formula[count])
del (formula[count])
return calculator(formula)
elif i == '/':
formula[count - 1] = str(float(formula[count - 1]) / float(formula[count + 1]))
del (formula[count])
del (formula[count])
return calculator(formula)
count += 1
count = 0
if formula[0] == '-': # 處理第一個字符是’-’的情況
formula[1] = formula[0] + formula[1]
del (formula[0])
for i in formula: # 處理加減
if i == '+':
formula[count - 1] = str(float(formula[count - 1]) + float(formula[count + 1]))
del (formula[count])
del (formula[count])
return calculator(formula)
elif i == '-':
formula[count - 1] = str(float(formula[count - 1]) - float(formula[count + 1]))
del (formula[count])
del (formula[count])
return calculator(formula)
count += 1
return float(formula[0]) # 返回float型的運算結果
if __name__ == '__main__':
formula = "".join(sys.argv[1:])
formula = conversionFormula(formula)
if formula != 'ERROR': # 錯誤判斷
formula = remove_bracket(formula)
answer = calculator(formula)
if float(answer).is_integer() == True:
answer = int(answer)
else:
answer = format(answer, '.10f') # 空格補0,不足位數不補0
answer = float(str(answer).rstrip('0'))
print(answer)
else:
a = 1