计算器实例

计算器实例

一、文字思路分析

拿到一个表达式,例如 ‘3+ (-80/2)+ 24*5-(18/3+ 4*(90/15-100) -3)’,通过这个表达式,我们除了考虑到数学的运算法则之外,还应该考虑到输入表达式过程存在的输入格式问题

1、格式问题:表达式中存在空格,就要去除空格

2、运算法则:有括号先去括号,先计算括号里面的没有括号的表达式;先算乘除再算加减;正负号问题,正负得负,负负得正

3、运用正则表达式去匹配表达式中的对应的项,然后计算

4、每一项计算出来都得反馈回那一项所在的地方

5、有重复的东西,需要用到循环

二、分模块进行计算(代码)

  • 1、去空格模块
exp = '3+ (-80/2)+ 24*5-(18/3+ 4*(90/15-100) -3)'

new_exp = exp.replace(' ','')
print(new_exp)

运行结果:

3+(-80/2)+24*5-(18/3+4*(90/15-100)-3)

 

  • 2、匹配和计算括号里面没有括号的项

先用正则表达式找出括号里面没有括号的项

ret = re.search('\([^()]+\)',new_exp)
if ret:
    exp_no_bracket = ret.group()  # 筛选出括号里面没有括号的表达式

print(exp_no_bracket)

运行结果:

(-80/2)

将括号里面没有括号的项去括号,然后找出单纯的乘除项,利用调用函数的方法,计算乘除结果

def cal_exp_no_bracket(ex):  # ex是括号里面没有括号的项
    ex = ex.strip('()')  # 将里面没有括号的项的括号去除
    # 计算先乘除后加减
    ret = re.search('\d+\.?\d*[*/]-?\d+\.?\d*',ex)  # 利用正则表达式找第一个出现的乘除的项
    if ret:
        ex_son = ret.group()  # 子表达式,最简单的只有乘除法
        print(ex_son)
....
....
ret = cal_exp_no_bracket(exp_no_bracket) # 调用计算括号里面没有括号的函数
new_exp = new_exp.replace(exp_no_bracket,ret)  # 将计算括号里面没有括号的最后的值代替对应的项
print(new_exp)


运行结果:

80/2

 计算原子表达式,即最简的原子形式表达式

def cal_ex_son(ex_son):
    if '/' in ex_son:
        a,b, = ex_son.split('/')
        return str(float(a)/float(b))
    elif '*' in ex_son:
        a,b, = ex_son.split('*')
        return str(float(a) * float(b))
....
.... ret
= cal_ex_son(ex_son) # 调用计算原子表达式的函数 print(ret) new_ex = ex.replace(ex_son,ret) # 将最终计算的值替代原来括号里面没有括号的那一项

运行结果应该是:

-40.0
3+-40.0+24*5-(18/3+4*(90/15-100)-3)

 

  • 3、匹配和计算加减法
 ret = re.findall('-?\d+\.?\d*',ex)
            sum = 0
            for i in ret:
                sum += float(i)
            return str(sum)

 

  • 4、正负符号的处理
正负得负,负负得正
# 正负符号的处理,正负得负,负负得正
def dealwith(exp):
    exp = exp.replace('+-','-')
    exp = exp.replace('--','+')
    return exp
....
.... new_exp
= dealwith(new_exp) print(new_exp)

运行结果应该是:

3-40.0+24*5-(18/3+4*(90/15-100)-3)

 

 

  • 5、main程序

通过函数的调用和嵌套,一步一步计算

# 要计算的表达式
exp = '3+ (-80/2)+ 24*5-(18/3+ 4*(90/15-100) -3)'
# 去空格
new_exp = exp.replace(' ','')
print(new_exp)
res = remove_bracket(new_exp)
print(res)

 

三、计算器总模块代码 

以上的2和3和4点只是计算了第一个匹配到括号里面没有括号的项,以及第一个出现乘除的项,和第一个出现加减法的项,要计算全部的这样的项,需要利用循环,去实现,主要式寻找和计算括号里面没有括号的项,还有寻找和计算简单的乘除以及加减式子需要反复寻找计算,最后整理的计算器的大致框架:

import re  # 导入re模块,正则表达式需要

# 正负符号的处理,正负得负,负负得正
def dealwith(exp):
    exp = exp.replace('+-','-')
    exp = exp.replace('--','+')
    return exp


# 计算原子形式的表达式,两个数的乘除法
def cal_ex_son(ex_son):
        if '/' in ex_son:
            a,b, = ex_son.split('/')
            return str(float(a)/float(b))
        elif '*' in ex_son:
            a,b, = ex_son.split('*')
            return str(float(a)*float(b))
        else:
            print('所有的乘除式子都计算好了')


# 计算最简的括号里面没有括号的式子,先计算乘除法,再计算加减
def cal_exp_no_bracket(ex):  # ex是括号里面没有括号的项
    ex = ex.strip('()')  # 将里面没有括号的项的括号去除  # 计算先乘除后加减
    while True:  # 利用循环找到括号里面不再有括号的项
        ret = re.search('\d+\.?\d*[*/]-?\d+\.?\d*',ex)  # 利用正则表达式找第一个出现的乘除的项
        if ret:  # 说明表达式中还有乘除法
            ex_son = ret.group()  # 子表达式,最简单的只有乘除法,原子形式
            print('匹配到只有乘除法的项: ',ex_son)
            ret = cal_ex_son(ex_son)  # 调用计算原子表达式的函数
            ex = ex.replace(ex_son,ret)  # 将最终计算的值替代原来括号里面没有括号的那一项
            ex = dealwith(ex)
        else:  # 说明表达式中没有乘除法,然后计算加减法
            ret = re.findall('-?\d+\.?\d*',ex)
            sum = 0
            for i in ret:
                sum += float(i)
            return str(sum)


# 筛选出括号里面没有括号的表达式,并且开始计算
def no_bracket_in_bracket(new_exp):
    while True:  # 利用循环找到所有的一层一层里面没有括号的项
        ret = re.search('\([^()]+\)',new_exp)
        if ret:
            exp_no_bracket = ret.group()  # 筛选出括号里面没有括号的表达式
            print('匹配到内部不再有括号的项: ',exp_no_bracket)
            ret = cal_exp_no_bracket(exp_no_bracket)  # 调用计算括号里面没有括号的项
            print(ret)
            new_exp = new_exp.replace(exp_no_bracket,ret)  # 将计算括号里面没有括号的最后的值代替对应的项
            new_exp = dealwith(new_exp)
            print(new_exp)
        else:
            print('表达式中没有括号了: ',new_exp)
            ret = cal_exp_no_bracket(new_exp)
            print(ret)
            break


# 主程序,要计算的表达式
exp = '3+ (-80/2)+ 24*5-(18/3+ 4*(90/15-100) -3)'
# 去空格
new_exp = exp.replace(' ','')
print(new_exp)
res = no_bracket_in_bracket(new_exp)
print(res)

运行结果:

3+(-80/2)+24*5-(18/3+4*(90/15-100)-3)
匹配到内部不再有括号的项:  (-80/2)
匹配到只有乘除法的项:  80/2
-40.0
3-40.0+24*5-(18/3+4*(90/15-100)-3)
匹配到内部不再有括号的项:  (90/15-100)
匹配到只有乘除法的项:  90/15
-94.0
3-40.0+24*5-(18/3+4*-94.0-3)
匹配到内部不再有括号的项:  (18/3+4*-94.0-3)
匹配到只有乘除法的项:  18/3
匹配到只有乘除法的项:  4*-94.0
-373.0
3-40.0+24*5+373.0
表达式中没有括号了:  3-40.0+24*5+373.0
匹配到只有乘除法的项:  24*5
456.0
None

Process finished with exit code 0

 

posted @ 2019-07-02 21:43  且行且cherish  阅读(483)  评论(0编辑  收藏  举报