50行代码实现python计算器主要功能

实现功能:计算带有括号和四则运算的式子   3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)

 

基本思路:使用正则表达式提取出每一层小括号式子,计算出结果后替换该括号,直至最后一层。

0、计算前的准备,进行式子的整理,如果非法则退出。这里我只对空格和符号进行了处理,真实场景中应该做更多的判断:

def check(s):
    s = s.replace(" ", '')
    s = re.sub(r'(\+-)|(-\+)', '-', s)
    s = re.sub(r'(\+\+)|(--)', '+', s)
    return s

 

1、只有加减运算的式子:findall匹配后直接使用sum函数对list求和,此时的减号看作负号,加号看作了正号,所以代码极其简洁:

import re

def plus_all(s): #实现加减运算
    patter_plus = r'[+-]?\d+\.?\d*'
    ret = re.findall(patter_plus, s)
    return sum([float(x) for x in ret])

 2、只有乘除运算的式子:和以上思路一致,主要想把除法(/)转换为乘法后用reduce计算。其先匹配出带有乘除运算符的list,然后通过change_mul_div()函数将除法转换成倒数计算

from functools import reduce

def mul_all(s):
    patter_mul = r'[*/]?[-]?\d+\.?\d*'
    ret = re.findall(patter_mul, s)
    return reduce(lambda m, n: m*n, [change_mul_div(x) for x in ret])


def change_mul_div(s):
    if "/" in s:
        return 1 / float(s.replace('/', ""))
    else:
        return float(s.replace("*", ''))

 3、含有加减乘除但不含有括号的式子:先用mul_all(s)函数将式子中的所有乘除法计算完毕,然后回到第1步。cal_all_mul_div函数实现计算式子中所有乘除法:

def cal_all_mul_div(s):
    patter_all_mul_div = r'([+-]?\d+\.?\d*[*/])+[+-]?\d+\.?\d*'
    ret = re.search(patter_all_mul_div, s)
    while ret:
        mul_div = mul_all(ret.group())
        s = s.replace(ret.group(), ''.join(['+', str(mul_div)]))
        ret = re.search(patter_all_mul_div, s)
    return s

 4、不断提取括号进行计算:

def bracket(s):
    patter_kuohao = r'\([^()]+\)'
    ret = re.search(patter_kuohao, s)
    while ret:
        cal_result = plus_all(cal_all_mul_div(ret.group()))
        s=s.replace(ret.group(), ''.join(['+', str(cal_result)]))
        ret = re.search(patter_kuohao, s)
    return s

 

 

所有代码合并如下:

import re
from functools import reduce

s3 = "3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)"

def check(s):
    s = s.replace(" ", '')  #对空格进行处理
    s = re.sub(r'(\+-)|(-\+)', '-', s)   #对符号进行处理
    s = re.sub(r'(\+\+)|(--)', '+', s)
    return s

def plus_all(s):
    patter_plus = r'[+-]?\d+\.?\d*'
    ret = re.findall(patter_plus, s)   #找出所有的加数
    return sum([float(x) for x in ret])  #生成器生成列表并求和

def mul_all(s):
    patter_mul = r'[*/]?[-+]?\d+\.?\d*'
    ret = re.findall(patter_mul, s)
    return reduce(lambda m, n: m * n, [change_mul_div(x) for x in ret])  #reduce连乘

def change_mul_div(s):   #把除法改成乘以其倒数
    if "/" in s:
        return 1 / float(s.replace('/', ""))
    else:
        return float(s.replace("*", ''))

def cal_all_mul_div(s):
    patter_all_mul_div = r'([+-]?\d+\.?\d*[*/])+[+-]?\d+\.?\d*'
    ret = re.search(patter_all_mul_div, s)
    while ret:
        mul_div = mul_all(ret.group())
        s = s.replace(ret.group(), ''.join(['+', str(mul_div)]))
        ret = re.search(patter_all_mul_div, s)
    return s

def bracket(s):
    patter_kuohao = r'\([^()]+\)'
    s = check(s)
    ret = re.search(patter_kuohao, s)
    while ret:
        cal_result = plus_all(cal_all_mul_div(ret.group()))
        s = check(s.replace(ret.group(), ''.join(['+', str(cal_result)])))   #替换时需要在前面加入正号,并对s进行check操作
        ret = re.search(patter_kuohao, s)
    return s

s3 = ''.join(["(", s3, ")"])
print(float(bracket(s3)))

 

 

 

以上即用不超过50行代码实现了计算器的主要功能。

 

posted @ 2018-01-20 21:50  廖Sir  阅读(550)  评论(0编辑  收藏  举报