Python使用正則實現(xiàn)計算字符串算式
在Python里面其實有一種特別方便實用的直接計算字符串算式的方法
那就是eval()
s = '1+2*(6/2-9+3*(3*9-9))' print(eval(s)) #97.0
好了,我現(xiàn)在就是想用正則寫一個類似這樣功能的東西
第一步,我們拿到一個算式,例如'1+2*(6/2-9+3*(3*9-9))'
按照我們小學學的知識我們應該知道我們應該從最內(nèi)層括號里面的算式開始計算
那我們怎么拿到最內(nèi)層括號里面的算式呢?我們可以用正則啊
import re pattern = re.compile(r'\([^(^)]*?\)') s = '1+2*(6/2-9+3*(3*9-9))+(6-3)' ret = pattern.findall(s) print(ret) #['(3*9-9)','(6-3)']
好了,我們現(xiàn)在就拿到了最內(nèi)層括號以及里面的算式了,第一步完成
第二步,我們要把拿到的內(nèi)容給它去掉括號
因為我們拿到的最內(nèi)層的括號可能不止一個,所以我們用一個新的列表來存一下去掉括號里面的算式
ret2 = []
pattern2 = re.compile(r'\((?P<tag>.*?)\)')
for i in range(len(ret)):
ret3 = pattern2.search(ret[i])
ret2.append(ret3.group('tag'))
print(ret2)
#['3*9-9', '6-3']
其實到這里我們幾乎已經(jīng)成功一大半了
第三步,我們就要來安排我們拿到的最內(nèi)層括號的算式了
這里只展示邏輯,我就只拿'3*9-9'(ret2[1])來說了
我們還是得根據(jù)算術邏輯來,先乘除,后加減
乘除
def mul_div(s):
if '*' in s:
s = s.split('*')
return float(s[0]) * float(s[1])
elif '/' in s:
s = s.split('/')
return float(s[0]) / float(s[1])
while True:
pattern3 = re.compile(r'[-+*/]?(?P<tag>-?\d+(\.\d+)?[*/]-?\d+(\.\d+)?)')
ret3 = pattern3.search(ret2[1])
try:
ret4 = ret3.group('tag')
except Exception as e:
pass
if '*' not in ret2[1] and '/' not in ret2[1]:
break
else:
ret2[1] = ret2[1].replace(ret4, str(mul_div(ret4)))
這里的代碼,可能看不明白,我來解釋一下
首先mul_div()就是自己定義的一個計算乘除法的方法
因為正則表達式的約束,并且用的是search,所以一下得到的字符串只可能是字符+'/'+字符或者字符+'*'+字符。所以這里字符串切割,必定會根據(jù)乘除號切成兩個元素的列表
我們算出了字符+'/'+字符或者字符+'*'+字符的值,我們就要用算出來的值替換掉正則匹配的字符串,直到這個字符串中沒有乘除號
加減
def add_sub(s):
if '+' in s:
s = s.split('+')
return float(s[0]) + float(s[1])
else:
if s[0] == '-':
s = s[1::].split('-', 1)
s[0] = '-' + s[0]
return float(s[0]) - float(s[1])
else:
s = s.split('-', 1)
return float(s[0]) - float(s[1])
while True:
pattern3 = re.compile(r'-?\d+(\.\d+)?[-+]-?\d+(\.\d+)?')
ret3 = pattern3.search(ret2[i])
try:
ret4 = ret3.group()
except Exception as e:
pass
if '+' not in ret2[i] and '-' not in ret2[i][1::]:
break
else:
ret2[i] = ret2[i].replace(ret4, str(add_sub(ret4)))
加減法和上面的乘除法沒多少區(qū)別
唯一的區(qū)別就是判斷退出時,一個數(shù)可能是負數(shù),就不能直接判斷負號存不存在了,就要判斷除了第一個位置,其余的位置還存不存在負號
第四步
在這里,我們所有最內(nèi)層括號算出來的數(shù)都在ret2這個列表里面,我們ret1中存放的是最內(nèi)層括號以及里面的算式,所以我們將兩者替換就可以了
def str_replace(lst1,lst2): for i in range(len(lst1)): global str1 str1 = str1.replace(lst1[i], lst2[i]) str_replace(ret1,ret2)
第五步
其實到這里我們離成功就差一小步了
可能你已經(jīng)發(fā)現(xiàn)了,我們這一套下來,就是對一個括號內(nèi)的算式進行運算,如果沒有括號它最后就不會對它進行操作,那我們就在字符串進來的時候給最外層套一個括號就OK了
str1 = '1+2*(6/2-9+3*(3*9-9))'
str1 = '( )'.replace(' ',str1)
然后拿到一個算式一直重復上面的幾個步驟,直到?jīng)]有括號。
完整代碼
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
# 乘除法
def mul_div(s):
if '*' in s:
s = s.split('*')
return float(s[0]) * float(s[1])
elif '/' in s:
s = s.split('/')
return float(s[0]) / float(s[1])
# 加減法
def add_sub(s):
if '+' in s:
s = s.split('+')
return float(s[0]) + float(s[1])
else:
if s[0] == '-':
s = s[1::].split('-', 1)
s[0] = '-' + s[0]
return float(s[0]) - float(s[1])
else:
s = s.split('-', 1)
return float(s[0]) - float(s[1])
# 替換字符串
def str_replace(lst1,lst2):
for i in range(len(lst1)):
global str1
str1 = str1.replace(lst1[i], lst2[i])
# 匹配最內(nèi)層括號
pattern1 = re.compile(r'\([^(^)]*?\)')
str1 = '1+2*(6/2-9+3*(3*9-9))'
str1 = '( )'.replace(' ',str1)
while True:
if '(' not in str1 and ')' not in str1:
break
ret1 = pattern1.findall(str1)
# 匹配括號內(nèi)的內(nèi)容
ret2 = []
pattern2 = re.compile(r'\((?P<tag>.*?)\)')
for i in range(len(ret1)):
ret = pattern2.search(ret1[i])
ret2.append(ret.group('tag'))
# 計算乘除法
while True:
pattern3 = re.compile(r'[-+*/]?(?P<tag>-?\d+(\.\d+)?[*/]-?\d+(\.\d+)?)')
ret3 = pattern3.search(ret2[i])
try:
ret4 = ret3.group('tag')
except Exception as e:
pass
if '*' not in ret2[i] and '/' not in ret2[i]:
break
else:
ret2[i] = ret2[i].replace(ret4, str(mul_div(ret4)))
# 計算加法
while True:
pattern3 = re.compile(r'-?\d+(\.\d+)?[-+]-?\d+(\.\d+)?')
ret3 = pattern3.search(ret2[i])
try:
ret4 = ret3.group()
except Exception as e:
pass
if '+' not in ret2[i] and '-' not in ret2[i][1::]:
break
else:
ret2[i] = ret2[i].replace(ret4, str(add_sub(ret4)))
str_replace(ret1,ret2)
print(str1)
#97.0
結(jié)束語
希望以后有人看到了,就不要吐槽我的ret1-ret4的變量命名了
還有不知道有沒有寫清楚,看的人能不能看明白,畢竟一晚上沒睡覺,可能腦子不好使。
我這代碼肯定有很多值得優(yōu)化的地方,所以僅供參考。
哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
總結(jié)
以上所述是小編給大家介紹的Python使用正則實現(xiàn)計算字符串算式,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
- python獲取指定字符串中重復模式最高的字符串方法
- Python實現(xiàn)統(tǒng)計給定字符串中重復模式最高子串功能示例
- Python字符串的修改方法實例
- Python中修改字符串的四種方法
- Python中字符串的修改及傳參詳解
- Python 字符串操作方法大全
- python字符串連接的N種方式總結(jié)
- Python實現(xiàn)字符串與數(shù)組相互轉(zhuǎn)換功能示例
- python分割和拼接字符串
- Python內(nèi)置的字符串處理函數(shù)整理
- python統(tǒng)計字符串中指定字符出現(xiàn)次數(shù)的方法
- python實現(xiàn)修改固定模式的字符串內(nèi)容操作示例

