簡單版的計算器

計算器開發需求

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

思路:

  1. 字符串預處理,將所有空格去除
  2. 判斷是否存在括號運算,若存在進行第3步,若不存在則直接進入第4步
  3. 利用正則表達式獲取最底層括號內的四則運算表達式
  4. 利用re.split()、re.findall()方法,通過加減符號,對四則運算進行拆分爲乘除運算式和數字
  5. 判斷表達式開頭有負數時,如果有,將負號放在第二個值中
  6. 利用re.split()、re.findall()方法,通過乘除符號,將乘除式拆分爲乘除符號與數字,然後進行計算,並返回數值
  7. 完成所有乘除運算之後,返回進行加減運算
  8. 完成加減運算後,返回表達式進行替代
  9. 通過遞歸函數,完成所有括號運算後。最後再完成一次四則運算即可完成所有運算
# Author: 73
'''
1、字符串預處理,將所有空格去除
2、判斷是否存在括號運算,若存在進行第3步,若不存在則直接進入第4步
3、利用正則表達式獲取最底層括號內的四則運算表達式
4、利用re.split()、re.findall()方法,通過加減符號,對四則運算進行拆分爲乘除運算式和數字
5、判斷表達式開頭有負數時,如果有,將負號放在第二個值中
6、利用re.split()、re.findall()方法,通過乘除符號,將乘除式拆分爲乘除符號與數字,然後進行計算,並返回數值
7、完成所有乘除運算之後,返回進行加減運算
8、完成加減運算後,返回表達式進行替代
9、通過遞歸函數,完成所有括號運算後。最後再完成一次四則運算即可完成所有運算
'''

import re

def compute_multiply_and_dividend(i):
    print(i)
    operators = re.findall('[*/]', i)
    calc_list = re.split('[*/]', i)
    res = None
    for index, j in enumerate(calc_list):
        if res:
            if operators[index - 1] == '*':
                res *= float(j)
            elif operators[index - 1] == '/':
                res /= float(j)
        else:
            res = float(j)

    print("\033[31;1m[%s]運算結果等於==\033[0m" % i, res)
    return res

def remove_duplicates(formula): # -9-2-5-2*3-5/3-40*4/2-3/5+6*3
    formula = formula.replace("++", "+")
    formula = formula.replace("+-", "-")
    formula = formula.replace("-+", "-")
    formula = formula.replace("--", "+")
    return formula

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(s):
    '''這裏計算的是不帶括號的公式'''
    s = s.strip("()") # 取出外面包的括號
    s = remove_duplicates(s) # 去除外重複的+-號
    plus_and_minus_operators = re.findall('[+-]', s) # 取出所有的+-
    print(plus_and_minus_operators)
    multiply_and_dividend = re.split('[+-]', s) # 取出乘除公式
    print(multiply_and_dividend)
    if len(multiply_and_dividend[0]) == 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)
    print('aaa', plus_and_minus_operators, multiply_and_dividend)

    for index, i in enumerate(multiply_and_dividend):
        if re.search('[*/]', i):
            sub_res = compute_multiply_and_dividend(i)
            multiply_and_dividend[index] = sub_res

    print(multiply_and_dividend, plus_and_minus_operators)

    total_res = None
    for index, i in enumerate(multiply_and_dividend):
        if total_res: # 代表不是第一次
            if plus_and_minus_operators[index-1] == '+':
                total_res += float(i)
            elif plus_and_minus_operators[index-1] == '-':
                total_res -= float(i)
        else:
            total_res = float(i)

    print("\033[31;1m[%s]運行結果:\033[0m" % s, total_res)
    return total_res

def calc(s):
    '''計算機程序主入口,優先級:括號>乘除>加減'''
    s = s.replace(" ", "")  # 去除所有的空格
    print(s)
    flag = True
    while flag:
        # 找到最裏層的括號
        m = re.search("\([^()]*\)", s)
        if m:
            print("先算括號裏的值:", m.group())
            sub_res = compute(m.group())
            s = s.replace(m.group(), str(sub_res))
        else:
            print('\033[41;1m----沒拓號了...---\033[0m')
            print(s)

            print('\n\n\033[42:1m最終結果:\033[0m', compute(s))
            flag = False  # 代表公式裏的拓號都沒了

if __name__ == "__main__":
    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) )")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章