首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >验证数学表达式的正则表达式

验证数学表达式的正则表达式
EN

Stack Overflow用户
提问于 2016-02-22 17:46:33
回答 1查看 5K关注 0票数 0

我试图确定给定的输入是否是有效的数学表达式。这是我提出的当前代码,但只有当输入是单个整数(例如100、200、5、7)时,它才会返回true。

代码语言:javascript
复制
Pattern pattern = Pattern.compile("-?\\w+|[-+*%/()]");
Matcher match = pattern.matcher(Input);

if(pattern.matcher(Input).matches())
{
    System.out.print("True");
}
else
    System.out.print("False");

关于我正在努力完成的任务的更多信息:

为了简单起见,假设整数仅为(因此没有变量和小数位)。

运算符是:+,-,*,/,%。

只有括号(所以没有括号或大括号)。

示例:

有效:

代码语言:javascript
复制
123  
1*2(3+4)%7  
3--4+5*-7  
13(12)+11-(7*15%(11-2)/4)  
(((((-99999)))))

无效

代码语言:javascript
复制
1+2)  
)5--  
3+*12  
)(++**//
(50)+12)

此外,如果可能的话,是否也可以简单解释Regex是如何工作的?我对这个话题很陌生。我从概念上理解它,但在我的代码中实现它有困难。

EN

回答 1

Stack Overflow用户

发布于 2016-02-26 17:47:08

正如一些评论所言,只要一个正则表达式匹配,你所要求的是不可能的。事实上,匹配平衡括号是经典的“简单正则表达式无法解决的问题”之一。只要数学表达式可以包含任意嵌套的括号,就不能用正则表达式验证它。

然而,验证一种较小的语言是可能的,然后我们可以将其构建为您的语言的验证例程,只需一点代码。较小的语言就像您的语言一样,但是有一个变化:不允许使用。然后,语言中的有效表达式如下所示:

代码语言:javascript
复制
INTEGER OP INTEGER OP INTEGER OP .... OP INTEGER

另一种说法是“INTEGER接零或多个OP INTEGER序列”。这可以转换为正则表达式,如下所示:

代码语言:javascript
复制
Pattern simpleLang = Pattern.compile("-?\\d+([-+*%/]-?\\d+)*");

所以-?\d+表示INTEGER[-+*%/]表示OP。好吧,现在我们该怎么用这个?首先,让我们修改它,在整数之间添加任意空格,并使模式成为一个static,因为我们将把这个验证逻辑封装在一个类中:

代码语言:javascript
复制
static Pattern simpleLang = Pattern.compile("\\s*-?\\d+(\\s*[-+*%/]\\s*-?\\d+)*\\s*");

(但请注意,我们不允许在负号和后面的数字之间留出空格,因此不允许使用3 - - 4,即使允许使用3 - -4 )。

现在,为了验证整个语言,我们需要做的是反复找到一个位于最里面括号级的块(所以,一个块本身不包含父块,但是被一个开闭p轮对包围),验证parens中的内容是否与简单的语言匹配,然后用一些整数替换这个块(包括周围的parens),用空格包围它,这样它就被认为与周围的东西分开了。所以逻辑是这样的:

  • expr进来的是11 - (7 * 15 % (11 - 2) / 4)
  • 最里面括号大小的块是11 - 2
  • 11 - 2与简单语言匹配吗?是!
  • (11 - 2)替换为整数。例如,使用1
  • expr现在是11 - (7 * 15 % 1 / 4)
  • 最里面括号大小的块是7 * 15 % 1 / 4
  • 7 * 15 % 1 / 4与简单语言匹配吗?是!
  • (7 * 15 % 1 / 4)替换为整数。例如,使用1
  • expr现在是11 - 1
  • 没有更多的父母,所以问:expr匹配简单的语言吗?是!

在代码中,这样做的结果是:

代码语言:javascript
复制
static Pattern simpleLang = Pattern.compile("\\s*-?\\d+(\\s*[-+*%/]\\s*-?\\d+)*\\s*");
static Pattern innerParen = Pattern.compile("[(]([^()]*)[)]");
public static boolean validateExpr(String expr) {
    while (expr.contains(")") || expr.contains("(")) {
        Matcher m = innerParen.matcher(expr);
        if (m.find()) {
            if (!simpleLang.matcher(m.group(1)).matches()) {
                return false;
            }
            expr = expr.substring(0,m.start()) + " 1 " + expr.substring(m.end());
        } else {
            // we have parens but not an innermost paren-free region
            // This implies mismatched parens
            return false;
        }
    }
    return simpleLang.matcher(expr).matches();
}

请注意,有一个称为“有效”的表达式是不被调用的:即表达式13(12)+11-(7*15%(11-2)/4)。这将被视为无效,因为在13到12之间没有运算符。如果您希望允许这种隐式乘法,最简单的方法是在简单语言中将(空格字符)添加为允许的运算符,因此将simpleLang更改为:

代码语言:javascript
复制
static Pattern simpleLang = Pattern.compile("\\s*-?\\d+(\\s*[-+ *%/]\\s*-?\\d+)*\\s*");
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35560389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档