python写计算器

python的内置函数eval()可以进行计算,如

print(eval("1-2*((60-30   +(-40/5   )*(9-2*5/3+7/3*99   /4*2998+10*568/14))-(-4*3)/(16-3*2))"))

运行结果

2776672.6952380957

可以自己写一个函数,用于计算。步骤如下:

python写计算器_第1张图片

import re

def compute_mul_div(arg):  # 计算乘除,接收列表[expression, 0]
    val = arg[0]    # 获取表达式
    mch = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val)  # 匹配乘法或除法
    if not mch:  # 如果没有乘法或除法   # 递归结束条件
        return   # 结束函数
    content = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val).group()  # 寻找第一个乘法或除法

    if len(content.split('*')) > 1:   # 如是*
        n1, n2 = content.split('*')
        value = float(n1) * float(n2)  # 计算乘法
    else:                               # 如是/
        n1, n2 = content.split('/')
        value = float(n1) / float(n2)   # 计算除法

    before, after = re.split('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val, 1)  # 等式用第一个乘法或除法分割成一个列表
    new_str = "%s%s%s" % (before, value, after)  # 替换原等式
    arg[0] = new_str  # 更改列表第一个元素
    compute_mul_div(arg)  # 继续执行该函数,直到没有乘法或除法

def compute_add_sub(arg):  # 计算加减,参数为列表,第一个值为止含有加减法的等式,第二个值为0
    while True:
        if arg[0].__contains__('+-') or arg[0].__contains__("++") or arg[0].__contains__('-+') or arg[0].__contains__(
                "--"):      # 字符串中的 __contains__ 方法返回布尔值,判断参数是否在字符串中,如果等式含有以上4中之一,则替换
            arg[0] = arg[0].replace('+-', '-')
            arg[0] = arg[0].replace('++', '+')
            arg[0] = arg[0].replace('-+', '-')
            arg[0] = arg[0].replace('--', '+')
        else:    # 结束循环
            break

    if arg[0].startswith('-'):  # 如果等式以-好开头
        arg[1] += 1   # 列表中第二个值 + 1
        arg[0] = arg[0].replace('-', '&')
        arg[0] = arg[0].replace('+', '-')
        arg[0] = arg[0].replace('&', '+')
        arg[0] = arg[0][1:]
    val = arg[0]
    mch = re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val)  # 匹配加法或减法
    if not mch:  # 如没有 ,结束函数
        return
    content = re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val).group()  # 第一个加法或减法
    if len(content.split('+')) > 1:   # 如是加法
        n1, n2 = content.split('+')
        value = float(n1) + float(n2)
    else:     # 减法
        n1, n2 = content.split('-')
        value = float(n1) - float(n2)

    before, after = re.split('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val, 1)  # 等式以第一个加法或减法分开
    new_str = "%s%s%s" % (before, value, after)  # 更新等式
    arg[0] = new_str  # 更新列表
    compute_add_sub(arg)  # 继续执行该函数,直到变成一个数字


def compute(expression):  # 先计算乘除,再计算加减
    inp = [expression, 0]  # 把无括号等式和0放入列表中
    compute_mul_div(inp)  # 把以上列表作为参数传给函数compute_mul_div,并执行该函数
    compute_add_sub(inp)
    if divmod(inp[1], 2)[1] == 1:
        result = float(inp[0])
        result = result * -1
    else:
        result = float(inp[0])
    return result


def exec_bracket(expression):  # 参数为没有空格的等式
    '''
    计算括号内的等式
    '''
    if not re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression):  # 匹配最内侧括号,如为空  # 递归结束条件
        final = compute(expression)
        return final    # 则结束此函数并执行compute函数
    content = re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression).group()  # 如有括号,获取第一个括号中内容

    before, nothing, after = re.split('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression, 1)

    print('before:', expression)

    content = content[1:len(content) - 1]  # 获取除了括号中的内容

    ret = compute(content)  # 计算括号中等式

    print('%s=%s' % (content, ret))  # 括号中等式 = 计算结果

    expression = "%s%s%s" % (before, ret, after)  # 重新赋值expression,计算结果代替了括号
    print('after:', expression)   # 替代后的表达式
    print("=" * 10, '上一次计算结束', "=" * 10)
    return exec_bracket(expression)  # 第一个括号消除,继续消除第二个括号,知道原等式中没有括号,就执行compute函数


if __name__ == "__main__":   # 运行程序
    inpp = "1-2*((60-30   +(-40/5   )*(9-2*5/3+7/3*99   /4*2998+10*568/14))-(-4*3)/(16-3*2))"
    inpp = re.sub('\s*', '', inpp)  # 把inpp中的空白符替换成空字符
    result = exec_bracket(inpp)
    print(result)

运行结果

before: 1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
-40/5=-8.0
after: 1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
========== 上一次计算结束 ==========
before: 1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
9-2*5/3+7/3*99/4*2998+10*568/14=173545.88095238098
after: 1-2*((60-30+-8.0*173545.88095238098)-(-4*3)/(16-3*2))
========== 上一次计算结束 ==========
before: 1-2*((60-30+-8.0*173545.88095238098)-(-4*3)/(16-3*2))
60-30+-8.0*173545.88095238098=-1388337.0476190478
after: 1-2*(-1388337.0476190478-(-4*3)/(16-3*2))
========== 上一次计算结束 ==========
before: 1-2*(-1388337.0476190478-(-4*3)/(16-3*2))
-4*3=-12.0
after: 1-2*(-1388337.0476190478--12.0/(16-3*2))
========== 上一次计算结束 ==========
before: 1-2*(-1388337.0476190478--12.0/(16-3*2))
16-3*2=10.0
after: 1-2*(-1388337.0476190478--12.0/10.0)
========== 上一次计算结束 ==========
before: 1-2*(-1388337.0476190478--12.0/10.0)
-1388337.0476190478--12.0/10.0=-1388335.8476190479
after: 1-2*-1388335.8476190479
========== 上一次计算结束 ==========
2776672.6952380957

和内置函数eval()计算结果一样。实际上python的eval函数原理也是一样。
正则表达式匹配括号
python写计算器_第2张图片

你可能感兴趣的:(python)