数学表达式 Python 的正则表达式

时间:2021-01-24 12:42:45

标签: python regex

我想推出一个能够匹配存储在 exp 中的数学表达式的正则表达式。

表达式的模式以括号开头和结尾,不能包含任何字母。表达式可以包含整数或浮点数,运算符可以是 +-*/**。表达式长度不限。

这是我的正则表达式:

import re
re.match(r'^[(]([(-]?([0-9]+)[)]??)([(]?([-+/*]([0-9]))?([.]?[0-9]+)?[)])[)]*$', exp)

但是我的正则表达式与某些字符串不匹配。 例如:

  • exp = '(( 200 + (4 * 3.14)) / ( 2 ** 3 ))'
  • exp = '(23.23+23)'
  • exp = '((23**2)/23)'
  • exp = '(23.34-(3*2))'

我是正则表达式新手,不知道是哪部分表达式有问题,麻烦大家见谅,希望有人能帮我解决。 非常感谢!

1 个答案:

答案 0 :(得分:1)

您可以将其视为“拆分”字符串,并将运算符作为分隔符。这将使您免于尝试在正则表达式中表示数字。

所以你只需要一个表达式来选取 5 个运算符和括号。这可以使用运算符之间的管道来表示,最长的运算符 (**) 排在第一位。

import re
symbols   = ["**","+","-","*","/","(",")"]    # longest first
tokens    = re.compile("("+"|".join(map(re.escape,symbols))+")")
            # placing symbols in a group makes re.split keep the separators

def tokenize(exp):
  parts = map(str.strip,tokens.split(exp)) # split and strip spaces
  return list(filter(None,parts))          # remove empty parts

exp = '(( 200 + (4 * 3.14)) / ( 2 ** 3 ))'
print(tokenize(exp))
['(', '(', '200', '+', '(', '4', '*', '3.14', ')', ')', '/', '(', '2', '**', '3', ')', ')']


exp = '(23.23+23)'
print(tokenize(exp))
['(', '23.23', '+', '23', ')']

exp = '((23**2)/23)'
print(tokenize(exp))
['(', '(', '23', '**', '2', ')', '/', '23', ')']

exp = '(23.34-(3*2))'
print(tokenize(exp))
['(', '23.34', '-', '(', '3', '*', '2', ')', ')']        

然后您可以执行第二遍并验证组件是运算符还是有效数字,并检查表达式是否格式正确,带有匹配的括号和交替的运算符/操作数。到那时,您将确切地知道表达式的哪一部分是不正确的。

例如:

def validate(exp):
    parts    = tokenize(exp)
    error    = ""
    pLevel   = 0
    previous = "$"
    for errorPos,part in enumerate(parts):
        pLevel += (part=="(")-(part==")")
        if pLevel<0: error="too many closing parentheses";break
        if part in "**+/)" and previous in "$**+-/(" :
            error = "missing operand";break 
        if part not in "**+-/)" and previous not in "$**+-/(":
            error = "missing operator";break
        previous = part
        if part in ["**","*","+","-","/","(",")"]: continue
        if all(p.isdigit() for p in part.split(".",1)): continue
        error = "invalid operand: " + part
        break
    if not error and pLevel!=0:
        errorPos,error = len(parts),"unbalanced parentheses"
    if not error and previous in "**+-/":
        errorPos,error = len(parts),"missing operand"
    if error:
        print("".join(parts))
        indent = " " * sum(map(len,parts[:errorPos]))
        print(indent+"^")
        print(indent+"|__ Error!",error)

...

validate('(( 200 + (4 * 3,14)) / ( 2 ** 3 ))')
                       
((200+(4*3,14))/(2**3))
         ^
         |__ Error! invalid operand: 3,14


validate('(( 200 + (4 * 3.14)) / ( 2 ** 3 )') 

((200+(4*3.14))/(2**3)
                      ^
                      |__ Error! unbalanced parentheses


validate('(( 200 + (4 * 3.14)))) / ( 2 ** 3 )') 

((200+(4*3.14))))/(2**3)
                ^
                |__ Error! too many closing parentheses


validate('(( 200 + *(4 * 3,14)) / ( 2 ** 3 ))')

((200+*(4*3,14))/(2**3))
      ^
      |__ Error! missing operand


validate('(( 200 + ()(4 * 3,14)) / ( 2 ** 3 ))')

((200+()(4*3,14))/(2**3))
       ^
       |__ Error! missing operand


validate('(( (200 + )(4 * 3,14)) / ( 2 ** 3 ))')

(((200+)(4*3,14))/(2**3))
       ^
       |__ Error! missing operand


validate('(( (200 + 2)(4 * 3,14)) / ( 2 ** 3 ))')

(((200+2)(4*3,14))/(2**3))
         ^
         |__ Error! missing operator
相关问题