首页 > 技术文章 > 正则实现计算器

findman 2017-08-23 16:11 原文

简单版

查找最子集的括号对,然后用eval计算搞定。

1 def computerString(s):
2     while True:
3         r = re.search("\([^\(\)]+\)", s)
4         if r:
5             s = s.replace(r.group(),str(eval(r.group()[1:-1])))
6         else:
7             break
8     return eval(s)

 

复杂版

重点在于需要自己实现eval函数

符号替换

1 def signReplace(s):
2     s = s.replace("--","+")
3     s = s.replace("-+","-")
4     s = s.replace("+-","-")
5     return s

 

乘法

 1 def mulStr(s):
 2     while True:
 3         r = re.findall("\-?\d+\.?\d*\*\-?\d+\.?\d*",s)
 4         if r:
 5             for c in r:
 6                 rd = re.findall("\-?\d+\.?\d*",c)
 7                 ret = float(rd[0])*float(rd[1])
 8                 s = s.replace(c,str(ret))
 9                 s = signReplace(s)
10         else:
11             break
12     return signReplace(s)

 

除法

 1 def mulStr(s):
 2     while True:
 3         r = re.findall("\-?\d+\.?\d*\*\-?\d+\.?\d*",s)
 4         if r:
 5             for c in r:
 6                 rd = re.findall("\-?\d+\.?\d*",c)
 7                 ret = float(rd[0])*float(rd[1])
 8                 s = s.replace(c,str(ret))
 9                 s = signReplace(s)
10         else:
11             break
12     return signReplace(s)

 

从左至右加减法

 1 def computerLtoR(s):
 2     while True:
 3         radd = re.search("^(\-?\d+\.?\d*)\+(\d+\.?\d*)",s)
 4         rsub = re.search("^(\-?\d+\.?\d*)\-(\d+\.?\d*)",s)
 5         if radd:
 6             ret = float(radd.groups()[0]) + float(radd.groups()[1])
 7             s = s.replace(radd.group(),str(ret))
 8         elif rsub:
 9             ret = float(rsub.groups()[0]) - float(rsub.groups()[1])
10             s =s.replace(rsub.group(),str(ret))
11         else:
12             break
13     return s

 

计算函数

1 def computerSub(s):
2     s = mulStr(s)
3     s = divStr(s)
4     s = computerLtoR(s)
5     return s

 

替换原eval函数

1 def computerString(s):
2     while True:
3         r = re.search("\([^\(\)]+\)", s)
4         if r:
5             s = s.replace(r.group(),str(computerSub(r.group()[1:-1])))
6         else:
7             break
8     return computerSub(s)

 


还存在的问题

  • 没有对非数字错误进行处理
  • 使用0,1取列表可能导致溢出

可改进的点

  • 对整形和单精度结果做处理,当结果为整形时不显示小数位

推荐阅读