python小练习之字符串四则运算式编码解题思路

首先循环查找最内层括号,对其中的运算式求解,然后将结果替换掉字符串中对应的运算式。循环求解直到整个运算式所有括号均被解。

对不含括号的运算式求解时从左到右,先循环解出所有除法,再循环解出所有乘法,再做加减法。

解括号

首先看题目案例:

'10-3*(20-10+(-10/5)*27/3/3-(-100)/(10-3*5))+(-2.5*-12)'

首先要提取内层括号内的所有字符,编写正则表达式如下:

'\(([^()]+?)\)'

# \(和\)是为了匹配左括号和右括号,注意左右括号在正则表达式表示分组的意思,所以要加\转义成原本括号的意思。
# [^()]字符组内^表示非,^()表示匹配不含括号的内容
# +?表示匹配内容为1个或多个,最小匹配模式
# ([^()]+?)表示对不含括号的内容作为分组提取

编写解括号的代码:

def cal(s):
    s = s.replace(' ', '')  # 去除字符串中所有空格,防止匹配出错
    while '(' in s or ')' in s:
        ret = re.findall('\(([^()]+?)\)', s)
        for i in ret:
            s = s.replace(f'({i})', count(i))  # count函数用来计算不含括号的加减乘除运算式
        s = s.replace('--', '+')  # 注意一:处理解括号后可能出现减负号的情况
    else:
        s = count(s)
    return s

解乘除

这里是计算不含括号的加减乘除运算式,首先要做除法,那么先要提取除法运算式左右两边的数字,编写正则表达式如下:

([-]?\d+\.\d+|[-]?\d+)/([-]?\d+\.\d+|[-]?\d+)

# [-]?表示可能存在负号
# \d+\.\d+表示匹配浮点数
# [-]?\d+表示匹配整数
# ([-]?\d+\.\d+|[-]?\d+)表示提取正负浮点数或正负整数
# ([-]?\d+\.\d+|[-]?\d+)/([-]?\d+\.\d+|[-]?\d+) 表示提取/两边的正负浮点数或正负整数

循环运算除法过程:

def count(s):
    while '/' in s:
        result = re.findall('([-]?\d+\.\d+|[-]?\d+)/([-]?\d+\.\d+|[-]?\d+)', s)
        for i in result:
            s = s.replace(f'{i[0]}/{i[1]}', f'{float(i[0]) / float(i[1])}')

循环运算乘法过程(乘法的正则和除法的正则只差一个运算符):

    while '*' in s:
        result = re.findall('([-]?\d+\.\d+|[-]?\d+)\*([-]?\d+\.\d+|[-]?\d+)', s)
        for i in result:
            if float(i[0]) < 0 and float(i[1]) < 0:  # 注意二:负数乘负数得正数
                s = s.replace(f'{i[0]}*{i[1]}', f'+{float(i[0]) * float(i[1])}')
            else:
                s = s.replace(f'{i[0]}*{i[1]}', f'{float(i[0]) * float(i[1])}')

解加减法

解加减法的感觉是最简单的一步,只要按上面的正则匹配出正负浮点数或正负整数,然后对所有数值累加即可。

    result = re.findall('([-]?\d+\.\d+|[-]?\d+)', s)
    x = 0
    for i in result:
        x += float(i)
    s = str(x)
    return s

完整代码

import re


def count(s):
    while '/' in s:
        result = re.findall('([-]?\d+\.\d+|[-]?\d+)/([-]?\d+\.\d+|[-]?\d+)', s)
        for i in result:
            s = s.replace(f'{i[0]}/{i[1]}', f'{float(i[0]) / float(i[1])}')

    while '*' in s:
        result = re.findall('([-]?\d+\.\d+|[-]?\d+)\*([-]?\d+\.\d+|[-]?\d+)', s)
        for i in result:
            if float(i[0]) < 0 and float(i[1]) < 0:
                s = s.replace(f'{i[0]}*{i[1]}', f'+{float(i[0]) * float(i[1])}')
            else:
                s = s.replace(f'{i[0]}*{i[1]}', f'{float(i[0]) * float(i[1])}')

    result = re.findall('([-]?\d+\.\d+|[-]?\d+)', s)
    x = 0
    for i in result:
        x += float(i)
    s = str(x)
    return s


def cal(s):
    s = s.replace(' ', '')
    while '(' in s or ')' in s:
        ret = re.findall('\(([^()]+?)\)', s)
        for i in ret:
            s = s.replace(f'({i})', count(i))
        s = s.replace('--', '+')
    else:
        s = count(s)
    return s

print(cal('10-3*(20-10+(-10/5)*27/3/3-(-100)/(10-3*5))'))
print(cal('10-3*(20-10+(-10/5)*27/3/3-(-100)/(10-3*5))+(-2.5*-12)'))
print(cal('10 - 3 * ( (50-30 +(-10/5) * (9-2*5/3 + 7 /3*99/4*2020 +10 * 789/15 )) - (-4*3)/ (16-3*2) )'))

out:
58.0
88.0
703066.4000000001

注意事项

注意一:处理解括号后可能出现减负号的情况。

注意二:负数乘负数得正数。

上述两条注意事项在编码时并未考虑到,后来运行程序发现结果不对,调试了很久才发现上述2个注意事项被忽略了,最后加上了2行代码后运算结果正确无误。

基本四则运算已经都非常熟悉了,但编码过程中还是会有疏漏。这在编写项目时经常会发生类似情况。程序员和需求方沟通时经常会发生类似情况,需求方经常因为有些是常识性的细节忘了提及,而程序员不精通业务需求方的业务,此时在需求方未提及的细节程序员也未考虑周全就会产生疏漏和bug。

所以加强沟通非常重要,程序员考虑需求全面且细致非常重要。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值