python實現計算器


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM