python實現簡單計算器
阿新 • • 發佈:2019-01-26
import re def remove_space(formula): """去掉算式的空格""" return formula.replace(" ", "") def change_symbol(formula): """ 提取負號 eg:-9-2-5-2*3-5/3-40*4/-1.0/5+6*3 ===> -(9+2+5+2*3+5/3+40*4/1.0/5-6*3) """ def primary_change(for_str): # 把算式中的 + - 對應換成 - + temp = for_str.split("+") new_formula = [] for value in temp: value = value.replace("-", "+") new_formula.append(value) return "-".join(new_formula) if formula.startswith("-"): formula = formula.replace("-", "", 1) formula = primary_change(formula) formula = formula.join(["-(", ")"]) elif formula.startswith("+"): formula = primary_change(formula) formula = formula.join(["-(", ")"]) else: formula = primary_change(formula) formula = formula.join(["-(-", ")"]) return formula def remove_repeat(formula): """去掉重複的運算子""" temp = formula.replace("++", "+") temp = temp.replace("+-", "-") temp = temp.replace("-+", "-") temp = temp.replace("--", "+") temp = temp.replace("*+", "*") temp = temp.replace("+*", "*") temp = temp.replace("/+", "/") temp = temp.replace("+/", "/") return temp def has_special_operator(formula, special_operator): """判斷是否有 *+ +- /- 之類的運算子""" for operator in special_operator: if formula.find(operator) != -1: return operator return "" def handle_special_operator(formula, operator): """ 如果有 "*-", "-*", "/-", "-/" 這些運算子, 提取負號,去掉重複的運算子 """ temp = "" regex = "\d*[.]?\d+" opera = operator.replace("*", "[*]") ret = re.compile(opera.join([regex, regex])) while ret.search(formula): search_res = ret.search(formula).group() if operator.find("*") != -1: temp = search_res.replace(operator, "*") elif operator.find("/") != -1: temp = search_res.replace(operator, "/") temp = "-".join(["", temp]) formula = formula.replace(search_res, temp, 1) return formula def calculator_formula(formula): """ 計算算式,這裡計算的是不帶括號的算式 計算次序是 / * - + 計算過程中出現括號則停止計算,返回當前的算式 """ def primary_operator(for_str, operation): primary_result = 0 regex = "\d*[.]?\d*" ret = re.compile(operation.join(["[", "]"]).join([regex, regex])) while ret.search(for_str): ret_opera = has_special_operator(for_str, ["*-", "-*", "/-", "-/"]) while ret_opera: for_str = handle_special_operator(for_str, ret_opera) ret_opera = has_special_operator(for_str, ["*-", "-*", "/-", "-/"]) while has_special_operator(for_str, ["+-", "-+", "++", "--", "+*", "*+", "+/", "/+"]): for_str = remove_repeat(for_str) # print("primary_operator:", for_str) if has_parentheses(for_str): return for_str if for_str.startswith("-"): temp = re.findall("^-\d*[.]?\d*$", for_str) if temp: return temp[0] return change_symbol(for_str) if for_str.startswith("+"): for_str = for_str.replace("+", "", 1) if not ret.search(for_str): continue search_res = ret.search(for_str).group() operand_list = search_res.split(operation) if operation == "/": primary_result = float(operand_list[0]) / float(operand_list[1]) elif operation == "*": primary_result = float(operand_list[0]) * float(operand_list[1]) elif operation == "-": primary_result = float(operand_list[0]) - float(operand_list[1]) elif operation == "+": primary_result = float(operand_list[0]) + float(operand_list[1]) for_str = for_str.replace(search_res, str(primary_result), 1) return for_str formula = primary_operator(formula, "/") formula = primary_operator(formula, "*") formula = primary_operator(formula, "-") formula = primary_operator(formula, "+") return formula def has_parentheses(formula): """判斷是否還有括號""" if re.search("[()]", formula): return True return False def remove_parentheses(formula): """ 去掉算式的括號,計算括號裡算式 """ parentheses = re.compile("\([^()]+\)") while parentheses.search(formula): search_res = parentheses.search(formula).group() for_str = re.sub("[()]", "", search_res) if judge_illegal(for_str): return "" for_str = calculator_formula(for_str) formula = formula.replace(search_res, for_str, 1) # print("remove_parentheses:", formula) """ 會有去掉所有括號算式還沒算完的情況 eg:1-2*65 需要再計算一遍算式 """ formula = calculator_formula(formula) return formula def judge_illegal(formula): """ 判斷括號是否匹配完全,運算子是否合法 沒有考慮 ** // 的計算 """ if len(re.findall("[(]", formula)) != len(re.findall("[)]", formula)): return True if formula.startswith("*") or formula.startswith("/"): return True if has_special_operator(formula, ["*/", "/*", "**", "//"]): return True return False def calculator_result(formula): """ 去完括號後額外計算的那一次若再次出現括號, 則重複去括號運算,直至再沒有括號 """ formula = remove_space(formula) def first_calculator(for_str): if judge_illegal(for_str): return "" return remove_parentheses(for_str) formula = first_calculator(formula) while has_parentheses(formula): formula = first_calculator(formula) # print("calculator_result:", formula) if not formula: print("illegal formula!") return formula f = "23 + 13 * ((25+(-9-2-5-2*3-6/3-40*4/(2-3)/5+6*3) * (9-2*6/3 + 5 *3*9/9*5 +10 * 56/-14 )) - (-4*3)/ (3+3*3) )" print("result:", calculator_result(f)) # 輸出結果 13881.0 print("eval:", eval(f)) # 測試結果 13881.0