有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

正则表达式Java正则表达式性能问题

我正试图用Java制作一个函数绘图程序,它涉及到获取用户对将要绘制的函数的输入、解析和绘图。例如,用户可以输入x^2-y^2、cos(x+y)、log(x)-sqrt(y)等。该程序使用中缀二进制运算(+、-)等)和一元运算(cos、sqrt等)

简而言之,为了计算一元运算,我必须确保给定的表达式遵循单个一元运算的格式。例如,cos(x)、sqrt(x+y)和log(exp(y)-x)都适合这种格式,因为它们是一元运算,操作数是某种表达式;但是,sin(x)*cos(y)和1+log(x)等字符串不遵循此格式。为了检查,我为这种格式制作了一个正则表达式:

String unaryName = "((productlog)|(zeta)|(log)|(sqrt)|(cos)|(sin)|(tan)|(sec)|(csc)|(csc)|(abs)|(arccos)|(arcsin)|(arctan)|(arcsec)|(arccsc)|(arccot)|(gamma)|(exp))";

(这只是一个正则表达式,用于检查给定字符串是否是预定义一元操作的名称)

String unaryOperation = unaryName + "\\(([^\\(\\)]*(\\(.*\\))*[^\\(\\)]*)+\\)"

我会解释的。这个正则表达式正在寻找一元操作的名称。之后,它会查找左括号。在这之后,它寻找一些不是括号的字符序列,然后寻找一些以左括号开始,以右括号结束的序列。后者防止字符串“sin(x)+cos(y)”匹配

据我所知,这个正则表达式总是给出期望的结果。然而,在使用过程中,出现了一个问题。考虑这种情况:

String s = "cos(3) + sin(4)";
System.out.println(s.matches(unaryOperation));

显然,如果正则表达式起作用,它应该返回false,事实就是如此。这个例子也是如此:

String s = "cos(3.000) + sin(4)";
System.out.println(s.matches(unaryOperation));

就模式而言,一切都没有改变。然而,连续地将0添加到3之后,匹配的计算时间似乎会以指数形式延长。对我来说,12个零大约需要13秒。由于我的程序将在一个图形上绘制多个点,因此每次绘制某个图形时,它将不得不计算数千个表达式,因此这是一个致命的缺陷

我已经找到了一种方法来解决必须使用这个正则表达式的问题,我的程序运行得很好,但我仍然想知道:为什么这个正则表达式要花这么长时间来处理大型输入,有没有办法更改正则表达式来解决这个问题


共 (1) 个答案

  1. # 1 楼答案

    我怀疑问题是你的表达式在模式的中间是因为{{CD1}},所以做了回溯的EME>EME>回溯。试着用一个不情愿的量词替换它:.*?,或者更好的是(如果我理解逻辑的话),用[^\\)]*

    事实上,这难道不管用吗:

    String unaryOperation = unaryName + "\\([^\\)]*\\)";
    

    这将查找名称、左括号、任意数量的非右括号字符,然后是右括号。这假设您不想匹配以下内容:

    "cos(3 * (4 + x))"
    

    (你的模式也不匹配)