Java正则表达式性能问题

时间:2013-01-03 03:33:28

标签: java regex

我正在尝试用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));

没有什么真正改变,模式方面。但是,连续向3添加零,匹配似乎需要更长的时间来评估。对我来说,12个零需要大约13秒。由于我的程序将在图形上绘制许多点,因此每次绘制图形时都必须计算数千个表达式,因此这是一个致命的缺陷。

我已经找到了一种方法来使用这个正则表达式并且我的程序运行得非常好,但我仍然想知道:为什么这个正则表达式需要很长时间才能用于大输入,并且有任何改变正则表达式来修复这个问题的方法?

2 个答案:

答案 0 :(得分:1)

您可以使用此正则表达式

unaryName+"\\([^)]*(\\([^()]*\\))?[^(]*\\)"
                    ------------
                         |->starting from center.

我在这里检查圆括号是否正确平衡 ..这应该可以解决您的问题!

答案 1 :(得分:0)

我怀疑问题是你的表达式正在进行回溯的批次,因为模式中间有.*。尝试用不情愿的量词替换它:.*?或者更好(如果我理解逻辑),[^\\)]*

实际上,这不会成功:

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

这会查找名称,左括号,任意数量的非右括号字符,然后是右括号。这假设你不想匹配像

这样的东西
"cos(3 * (4 + x))"

(你的模式也不匹配)。