教學項目之-通過Python實現簡單的計算器


計算器開發需求

  1. 實現加減乘除及拓號優先級解析
  2. 用戶輸入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等類似公式后,必須自己解析里面的(),+,-,*,/符號和公式,運算后得出結果,結果必須與真實的計算器所得出的結果一致
import re
import functools


def minus_operator_handler(formula):
    '''處理一些特殊的減號運算'''
    minus_operators = re.split("-",formula)
    calc_list= re.findall("[0-9]",formula)
    if minus_operators[0] == '': #第一值肯定是負號
        calc_list[0] = '-%s' % calc_list[0]
    res = functools.reduce(lambda x,y:float(x) - float(y), calc_list)
    print("\033[33;1m減號[%s]處理結果:\033[0m" % formula, res )
    return res

def remove_duplicates(formula):
    formula = formula.replace("++","+")
    formula = formula.replace("+-","-")
    formula = formula.replace("-+","-")
    formula = formula.replace("--","+")
    formula = formula.replace("- -","+")
    return formula
def compute_mutiply_and_dividend(formula):
    '''算乘除,傳進來的是字符串噢'''
    operators = re.findall("[*/]", formula )
    calc_list = re.split("[*/]", formula )
    res = None
    for index,i in enumerate(calc_list):
        if res:
            if operators[index-1] == "*":
                res *= float(i)
            elif operators[index-1] == "/":
                res /= float(i)
        else:
            res = float(i)

    print("\033[31;1m[%s]運算結果=\033[0m" %formula, res  )
    return res
def handle_minus_in_list(operator_list,calc_list):
    '''有的時候把算術符和值分開后,會出現這種情況  ['-', '-', '-'] [' ', '14969037.996825399 ', ' ', '12.0/ 10.0 ']
       這需要把第2個列表中的空格都變成負號並與其后面的值拼起來,惡心死了
    '''
    for index,i in enumerate(calc_list):
        if i == '': #它其實是代表負號,改成負號
            calc_list[index+1] = i + calc_list[index+1].strip()
def handle_special_occactions(plus_and_minus_operators,multiply_and_dividend):
    '''有時會出現這種情況 , ['-', '-'] ['1 ', ' 2 * ', '14969036.7968254'],2*...后面這段實際是 2*-14969036.7968254,需要特別處理下,太惡心了'''
    for index,i in enumerate(multiply_and_dividend):
        i = i.strip()
        if i.endswith("*") or i.endswith("/"):
            multiply_and_dividend[index] = multiply_and_dividend[index] + plus_and_minus_operators[index] + multiply_and_dividend[index+1]
            del multiply_and_dividend[index+1]
            del plus_and_minus_operators[index]
    return plus_and_minus_operators,multiply_and_dividend
def compute(formula):
    '''這里計算是的不帶括號的公式'''

    formula = formula.strip("()") #去除外面包的拓號
    formula = remove_duplicates(formula) #去除外重復的+-號
    plus_and_minus_operators = re.findall("[+-]", formula)
    multiply_and_dividend = re.split("[+-]", formula) #取出乘除公式
    if len(multiply_and_dividend[0].strip()) == 0:#代表這肯定是個減號
        multiply_and_dividend[1] = plus_and_minus_operators[0] + multiply_and_dividend[1]
        del multiply_and_dividend[0]
        del plus_and_minus_operators[0]

    plus_and_minus_operators,multiply_and_dividend=handle_special_occactions(plus_and_minus_operators,multiply_and_dividend)
    for index,i in enumerate(multiply_and_dividend):
        if re.search("[*/]" ,i):
            sub_res = compute_mutiply_and_dividend(i)
            multiply_and_dividend[index] = sub_res

    #開始運算+,-
    print(multiply_and_dividend, plus_and_minus_operators)
    total_res = None
    for index,item in enumerate(multiply_and_dividend):
        if total_res: #代表不是第一次循環
            if plus_and_minus_operators[index-1] == '+':
                total_res += float(item)
            elif plus_and_minus_operators[index-1] == '-':
                total_res -= float(item)
        else:
            total_res = float(item)
    print("\033[32;1m[%s]運算結果:\033[0m" %formula,total_res)
    return total_res

def calc(formula):
    '''計算程序主入口, 主要邏輯是先計算拓號里的值,算出來后再算乘除,再算加減'''
    parenthesise_flag = True
    calc_res = None #初始化運算結果為None,還沒開始運算呢,當然為None啦
    while parenthesise_flag:
        m = re.search("\([^()]*\)", formula) #找到最里層的拓號
        if m:
            #print("先算拓號里的值:",m.group())
            sub_res = compute(m.group())
            formula = formula.replace(m.group(),str(sub_res))
        else:
            print('\033[41;1m----沒拓號了...---\033[0m')

            print('\n\n\033[42;1m最終結果:\033[0m',compute(formula))
            parenthesise_flag = False #代表公式里的拓號已經都被剝除啦

if __name__ == '__main__':

    #res = calc("1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")
    res = calc("1 - 2 * ( (60-30 +(-9-2-5-2*3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")

  


免責聲明!

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



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