python基础:正则科学计算器问题集

本文介绍如何使用正则表达式处理复杂的算术表达式,包括去除多重符号、处理浮点数及括号匹配等问题,并提供了一个完整的Python程序实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题一
str1 = re.sub("([^()])", result, str1),替换的时候会把当前到下一个)全部替换。
查看结果是因为默认多次替换原因导致
str1 = re.sub("\(*[^()]*\)", result, str1, count=1)
替换一次正常

问题二:
怎么精确的寻到一个-+,++,*+,/+等等的双重符号。。。像下面这样每句替换吗?

str1 = re.sub("++", "+",str1)
str1 = re.sub("-+", "-",str1)
str1 = re.sub("*+", "*",str1)
str1 = re.sub("/+", "/",str1)

NO,正则就是一个找规律的游戏,上面的句子完全可以一句替代:
str1 = re.sub('\W+', re.search('\W-', str1).group()[0], str1,count=1)
但是,上面有个问题遇到(3-2)+1,会把)+也给找出来,太不智能了,怎么办?
试试下面的:
str1 = re.sub('[*+/-]+', re.search('[*+/-]-', str1).group()[0], str1,count=1)
只认这四个,完美解决了)+的问题,oh yeah~

问题三:
运行整数时,程序正常,运行浮点,程序就出问题,因为多了.这个非数字字符。

问题四:
测试完美的程序,运算作业题时报错。
测试打印
-->2> 1-2*((60-30-1388360.0.88095238098+1.2.0
报错:

    subtotal += float(i)
ValueError: could not convert string to float: '-2*'

分析:为什么会出现乱码呢?
测试-(-5/3(8-10)+23)+33这样公式都可以,比较一下,发现了问题
题目的式子,是两个括号在一起的。。。。。。
1 - 2 ( (60-30 +(-40/5) (9-25/3 + 7 /399/42998 +10 568/14 )) - (-43)/ (16-32) )
改进后的正则:就算你有10个括号在一起,也不怕!
r"\([^\(+][\d+\W+][^\(\)]*[\W+\d+][^\)+]\)"

附代码:
#!--coding:utf-8--
import re

def parenthesis(str1) 获取最内层括号内的表达式,并用result函数的结果替换回表达式,循环去括号
def result(str1, i=0) 返回的是计算结果,str1是一个没有括号的表达式!

初始作业表达式

string = '1 - 2 ( (60-30 +(-40/5) (9-25/3 + 7 /399/42998 +10 568/14 )) - (-43)/ (16-32) )'
def result(str1, i=0):

计算没有括号的表达式结果,先算*/,再算加减。

while i < 2:                                # 两次,因为防止去完*- 和/-以后再次出现--/+-
    i += 1
    str1 = re.sub("--", "+", str1)       # 去括号的第一步,防止-(-1)出现,做替换
    str1 = re.sub("\+-", "-", str1)      # 去括号的第二步,防止+(-1)出现,做替换
    # print('str11-->%d>'%i, str1)
    # 去掉多余的加号。
    while re.search('[\*\+/-]\+', str1):
        str1 = re.sub('[\*\+/-]\+', re.search('[\*\+/-]\+', str1).group()[0], str1, count=1)
    # 开始[*/][-]运算
    opt = re.search('\d*[\.\d]\d*[\*/][\-]*\d*[\.\d]\d*', str1)            # 查找提取*/号和前后的数字,并作为循环条件
    while opt:
        opt = opt.group()                                               # 提取字符串
        if re.search('[\*/]-', opt):                                    # 判断减号
            sub_str = re.sub('[\*/]-', re.search('[\*/]', opt).group(), opt, count=1)   # 去掉减号
            symbol = '-'
        else:                                                           # 没有减号,不做处理
            symbol = ''
            sub_str = opt

        arithmetic = re.search('[\*/]', sub_str).group()                # 提取运算符
        num_list = re.search('(\d*[\.\d]\d*)[\*/](\d*[\.\d]\d*)', sub_str).groups()     # 提取运算符前后的数字
        # 用运算结果,替换掉str1中对应的字符,重新赋值给str1
        str1 = re.sub('\d*[\.\d]\d*[\*/][\-]*\d*[\.\d]\d*',
                      symbol+str(eval(str(num_list[0]+arithmetic+num_list[1]))), str1, count=1)
        opt = re.search('\d*[\.\d]\d*[\*/][\-]*\d*[\.\d]\d*', str1)            # 查找提取*/号和前后的数字,并作为循环条件

# 上面程序处理后,成为一个只有+-的字符串,下面处理+和-
if str1[0].isdigit():                       # 首位是数字,添加+号,为正则准备。
    str1 = '+' + str1
subtotal = 0                                # 初始化和值
opt = re.findall('(\W\d*[\.\d*]\d*)', str1)     # 带加减和数字的分组
for i in opt:                                     # 累加
    subtotal += float(i)
return str(subtotal)                                     # 返回计算结果

def parenthesis(str1):
str1 = re.sub(r'\s+', '', str1)
search = re.search(r"([^(+][\d+\W+][^()][\W+\d+][^)+])", str1) # 搜索最内层括号,并作为循环条件
while search:
str_sub = search.group()
temp = str_sub[1:-1] # 去掉括号
result_str = result(temp) # 调用算术运算函数
str1 = re.sub(r"([^(+][\d+\W+][^()]
[\W+\d+][^)+])", result_str, str1, count=1) # 括号内计算结果替换回去
search = re.search(r"([^(+][\d+\W+][^()]*[\W+\d+][^)+])", str1) # 搜索最内层括号
return str1

def error(str1):
try:
eval(str1)
except:
print('表达式错误!')
return True

程序开始

while True:
expression = input('[Q]退出,请输入算术表达式,例如:\n%s\n-->>' % string).strip()
if expression.lower() == 'q':
print('退出!')
break
print('您输入的表达式是:', expression)
if error(expression):
continue
else:
print('正则-运算结果是:', result(parenthesis(expression)))
print('EVAL-运算结果是:', eval(expression))
input('按任意键继续...')

转载于:https://blog.51cto.com/yishi/2048887

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值