用Python代碼寫的計算器


1.極限壓縮版

import re, functools
def cal(formula):
    while re.search('(?:\d+\.?\d+|\d+)[+\-*/]', formula):
        while re.search('[*/]', formula): formula = re.sub('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)', str(functools.reduce(lambda i, j: float(i) * float(j), re.search('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)', formula).group().split('*')) if '*' in re.search('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)', formula).group() else functools.reduce(lambda i, j: float(i) / float(j), re.search('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)', formula).group().split('/'))), formula, 1)
        if re.search('(?:\d+\.?\d+|\d+)[+\-]', formula): formula = re.sub('-?(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)', str(functools.reduce(lambda i, j: float(i) + float(j), re.search('-?(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)', formula).group().rsplit('+', 1)) if '+' in re.search('(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)', formula).group() else functools.reduce(lambda i, j: float(i) - float(j), re.search('-?(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)', formula).group().rsplit('-', 1))), formula, 1)
    return formula
formula = '1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
while re.search('\([^\(\)]+\)', formula):
    formula = re.sub('\([^\(\)]+\)', cal(re.search('\([^\(\)]+\)', re.sub('\s', '', formula)).group()).strip('()'), formula, 1)
    while re.search('[+\-*/]-', formula): formula = re.sub('[+]-', '-', formula) if '+-' in formula else re.sub('--', '', formula) if formula.startswith('--') else re.sub('(?:\d+\.?\d+|\d+)[*/]-', '-' + re.findall('(?:\d+\.?\d+|\d+)[*/](?=-)', formula)[0], formula) if re.search('[*/]-', formula) else re.sub('--', '+', formula)
print(cal(formula).split('.0')[0] if cal(formula).endswith('.0') else cal(formula))

 

2.完整版

import re
from functools import reduce


def plus_minus(formula):
    '''
    計算無括號的加減法算式
    :param formula: 等待計算的只包含加減法的字符串
    :return: 計算結果的字符串
    '''
    p1 = re.compile('-?(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)')  # 匹配一次加減法
    while re.search(p1, formula):  # 每次計算一個二元加減,並替換到原字符串上,直到計算並計算完所有數
        x = re.search(p1, formula).group()  # 匹配出一次計算,判斷是加法還是減法,再由reduce把分割后的兩個數交給匿名函數去計算。
        formula = re.sub(p1, str(reduce(lambda i, j: float(i) + float(j), x.rsplit('+', 1)) if '+' in x else reduce(lambda i, j: float(i) - float(j), x.rsplit('-', 1))), formula, 1)
    return formula
    # ps.計算加減法可以采用與乘除法不同的方式,可以把所有數全匹配出來再一起計算出來


def multi_divi(formula):
    '''
    計算無括號的乘除法算式
    :param formula: 等待計算的只包含乘除法的字符串
    :return: 計算結果的字符串
    '''
    p = re.compile('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)')
    while re.search(p, formula):
        y = re.search(p, formula).group()
        formula = re.sub(p, str(reduce(lambda i, j: float(i) * float(j), y.split('*')) if '*' in y else reduce(lambda i, j: float(i) / float(j), y.split('/'))), formula, 1)
    return formula


def parentheses_parse(formula):
    '''
    用來處理括號,並調用加減乘除完成計算
    :param formula: 數學算式的字符串,支持加減乘除和括號
    :return: 最終結果的整型或浮點型
    '''
    formula = re.sub('\s', '', formula)
    p = re.compile('\([^\(\)]+\)')  # 匹配內層括號
    while re.search(p, formula):  # 循環到沒有括號為止
        f = re.search(p, formula).group()
        formula = re.sub(p, plus_minus(multi_divi(f)).strip('()'), formula, 1)  # 調用加減法嵌套乘除法,計算完括號內的式子,並去除括號

        # 處理去除括號后可能出現的其他符號與負號相連的情況
        while re.search('[+\-*/]-', formula):
            formula = re.sub('[+]-', '-', formula)
            formula = re.sub('--', '', formula) if formula.startswith('--') else re.sub('--', '+', formula)  # 正負為負,負負為正,並且避免正號出現在最前端
            if re.search('[*/]-', formula):  # 遇到乘除連接負號的情況時,需要先把負號前置,再進行一次上面加減連接負號的處理
                n = re.search('(?:\d+\.?\d+|\d+)[*/](?=-)', formula).group()  # 這里使用正向預匹配獲得如'7*-'這樣的序列中的'7*'的部分
                formula = re.sub('(?:\d+\.?\d+|\d+)[*/]-', '-' + n, formula)  # 使用剛獲得的字符串進行替換,來使‘7*-’變成‘-7*’的樣子
    formula = plus_minus(multi_divi(formula))  # 沒有括號了,再計算最后一次
    if formula.endswith('.0'):  # 優化顯示
        formula = int(formula.split('.0')[0])
    else:
        formula = float(formula)
    return formula


# 在此處輸入算式
print(parentheses_parse('1-2*((60-  30+(-40/5)*(9  -2*5/3+7/3*99/4*2998+1  0*568/14))-(-4*3)/(16-3*2))'))

 

3.思路清晰版

import re
from functools import reduce

def mul_div(exp):
    """
    計算兩個數的乘法或者除法
    :param exp:
    :return:
    """
    if '*' in exp:
        a, b = exp.split('*')
        return float(a)*float(b)
    if '/' in exp:
        a, b = exp.split('/')
        return float(a) / float(b)

def exp_fmt(exp):
    """
    符號整理
    :param exp:
    :return:
    """
    while re.search('[+-]{2,}',exp):
        exp = exp.replace('--','+')
        exp = exp.replace('+-','-')
        exp = exp.replace('-+','-')
        exp = exp.replace('++','+')
    return exp

def remove_addsub(exp):
    """
    計算兩個數的加減法
    :param exp:
    :return:
    """
    ret = re.findall('[-+]?\d+(?:\.\d+)?',exp)
    res = reduce(lambda a,b:float(a)+float(b),ret)
    return res

def remove_muldiv(exp):
    """
    計算表達式中的所有的乘除法
    :param exp:
    :return:
    """
    while True:
        ret = re.search('\d+(\.\d+)?[*/]-?\d+(\.\d+)?',exp)
        if ret:
            son_exp = ret.group()
            res = mul_div(son_exp)
            exp = exp.replace(son_exp,str(res))
        else:return exp

def cal(exp):
    res = remove_muldiv(exp)            # 計算乘除
    res = exp_fmt(res)                  # 符號整理
    ret = remove_addsub(res)            # 計算加減
    return ret

def main(exp):
    exp = exp.replace(' ','')
    while True:
        ret = re.search('\([^()]+\)', exp)
        if ret:
            res = cal(ret.group())
            exp = exp.replace(ret.group(), str(res))
        else: return cal(exp)
exp = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
ret = main(exp)
print(ret)

 

待續


免責聲明!

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



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