【问题标题】:Regex capturing numbers before and after a symbol正则表达式捕获符号前后的数字
【发布时间】:2014-07-18 02:45:22
【问题描述】:

我希望能够将数学表达式/方程式发送到我的程序中,并让它给我结果答案。我正在使用正则表达式来解码要操作的数字。这是我当前的正则表达式代码:

Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*\\+\\s*(\\d+).*").matcher(e);
if(!m.matches()) return e;
e = ((int) Addition.add(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";

这适用于m.group(2) 中的第二个数字,但m.group(1) 只返回运算符符号之前的最后一个数字,我尝试了几种不同的方法,这是我最新的一个没有运气的方法。我做错了什么?

编辑:这是 3 种求解方法,它有一些我正在测试的测试输出。

public double solve(String e) {
    if (!validExpression(e))
        return 0;
    e = e.replace(" ", "");
    boolean doPar = false;
    if (e.contains("(") || e.contains(")")) {
        doPar = true;
        int par = 0;
        for (char c : e.toCharArray()) {
            if (c == '(')
                par++;
            else if (c == ')')
                par--;
        }
        if (par != 0)
            return 0;
    }
    if (doPar)
        e = solveParentheses(e);
    e = solveSmallExpression(e);
    return Double.parseDouble(e.replace("(", "").replace(")", ""));
}

private static String solveSmallExpression(String e) {
    System.out.println(e);
    while(e.contains("^")){
        final Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*\\^\\s*(\\d+).*").matcher(e);
        if(!m.matches()) return e;
        System.out.println(m.group(1) + "\t" + m.group(2));
        e = ((int) Exponentiation.raise(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
    }
    while(e.contains("/") || e.contains("*")) {
        if(e.contains("/")){
            final Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*/\\s*(\\d+).*").matcher(e);
            if(!m.matches()) return e;
            System.out.println(m.group(1) + "\t" + m.group(2));
            e = ((int) Division.divide(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
        }
        if(e.contains("*")){
            final Matcher m = Pattern.compile(".*\\D*(\\d{1,}+)\\s*\\*\\s*(\\d+).*").matcher(e);
            if(!m.matches()) return e;
            System.out.println(m.group(1) + "\t" + m.group(2));
            e = ((int) Multiplication.multiply(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
        }
    }
    while(e.contains("-") || e.contains("+")) {
        if(e.contains("-")){
            final Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*\\-\\s*(\\d+).*").matcher(e);
            if(!m.matches()) return e;
            System.out.println(m.group(1) + "\t" + m.group(2));
            e = ((int) Subtraction.subtract(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
        }
        if(e.contains("+")){
            final Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*\\+\\s*(\\d+).*").matcher(e);
            if(!m.matches()) return e;
            System.out.println(m.group(1) + "\t" + m.group(2));
            e = ((int) Addition.add(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
        }
    }
    System.out.println(e);
    System.out.println();
    return e;
}

private static String solveParentheses(String e) {
    while (e.contains("(") && e.contains(")")) {
        int start = -1;
        int end = -1;
        for(int i = 0; i < e.length(); i++) {
            char c = e.charAt(i);
            if(c == '(')
                start = i + 1;
            else if(c == ')')
                end = i;
        }

        String sub = e.substring(start, end);
        if(sub.contains("(") && sub.contains(")"))
            sub = solveParentheses(sub);
        sub = solveSmallExpression(sub);
        e = e.replace(e.subSequence(start - 1, end + 1), sub);
    }
    return e;
}

private static boolean validExpression(String e) {
    for (char c : e.toCharArray()) {
        if (!Character.isDigit(c) && c != '(' && c != ')' && c != '^' && c != '+' && c != '-' && c != '/' && c != '*' && c != ' ')
            return false;
    }
    return true;
}

当我打印这个时:
System.out.println((new ExpressionSolver()).solve("(24 * 100) - (24 / 12)"));
这是输出:

24/12
4   12
0

24*100
4   100
400

400-0
0   0
0

0.0

【问题讨论】:

  • 请提供一些示例输入和预期输出。
  • “数学表达式”太笼统了。你想支持括号吗?模数?对数?或者只是+-*/
  • 对于一般数学表达式解析,您应该实现一个解析器,例如 recursive decent parser

标签: java regex numbers capturing-group


【解决方案1】:

为什么不在两个组中使用相同的组声明?

表示使用 (\d+)

【讨论】:

    【解决方案2】:

    .* 是贪婪的,会吃掉整个字符串然后回滚,直到它碰到匹配的东西。由于您可以有 0 次出现非数字 (\D*) 并且需要至少一个数字和加号,因此正则表达式将在它回滚到足以达到该值时匹配。

    您可以使用“.*?”来解决此问题取而代之的是一个不情愿的运算符,它尽可能少地抓取字符。

    【讨论】:

    • 成功了!我不知道你可以使用? 来阻止贪婪的运营商。我知道它存在,但直到现在我才完全知道它做了什么。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 2014-08-27
    相关资源
    最近更新 更多