用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)

待续

猜你喜欢

转载自www.cnblogs.com/zangyue/p/12056160.html