正则表达式用于匹配数学表达式

时间:2019-05-15 19:28:00

标签: java regex

我目前负责验证给定表达式的格式是否正确。例如“ 7x ^ 2 + 2x +1”会通过,但“ 7x72”或格式错误的内容会失败。

尝试

\d*x{0,1}(\^\d*){0,1}

它检查每个函数,系数,可选x,可选指数是否存在。我只是不确定如何格式化它,以便它对于+/-号之间的每个部分都必须正确,否则该功能将无法正确键入。

如何解决此问题?

2 个答案:

答案 0 :(得分:2)

TL; DR 正则表达式为:

(?!$)(?:(-?\d*)x\^2)?(?:(?<=2)\s*([+-])\s*(?!-|^))?(?:(?<!2)(-?\d*)x)?(?:(?<=[2x])\s*([+-])\s*(?!-|^))?(?:(?<![2x])(-?\d+))?

完整语法为:

[ ['-'][number]'x^2' ] ['+' | '-'] [ ['-'][number]'x' ] ['+' | '-'] [ ['-']number ]

['-']表示数字的可选减号。

[number]是因为1的乘数可以省略,即使它是-1,例如-x-1x的有效简写。

['+' | '-']表示+-,标记为可选以使其简单,但实际上在部分之间是必需的,而本身是不允许的。这是使正则表达式变大的棘手部分。

因此,让我们进行构建:

part1: -?\d*x\^2
part2: -?\d*x
part3: -?\d+
OP   : \s*[+-]\s*(?!-)

(?!-)是为了防止在运算符之后出现减号。

剩下的是[part1] [OP] [part2] [OP] [part3],其中包含3个可选部分和两个可选运算符,不同之处在于部分必须由运算符分隔,并且运算符必须位于各部分之间,并且必须存在至少一个部分。

为确保存在某些内容,我们只需要防止空字符串,即以(?!$)开头的正则表达式,即字符串结尾处的零负负前瞻,也就是“在输入开始时,不在输入末尾。”

在正则表达式中,我们使用(?: xxx )?进行可选操作,即将一个非捕获组标记为可选,因此使每个部分和操作员都变得很容易。

到目前为止,我们有:

(?!$)(?:part1)?(?:OP)?(?:part2)?(?:OP)?(?:part3)?

现在开始处理棘手的部分:

  • 零件必须由操作员分隔

    这是最简单的测试,方法是确保part2不紧跟2(part1的最后一个字符),并且part3不紧跟2x (part1或part2的最后一个字符),因此我们将使用零宽度的负向后查找。

    (?:(?<!2)part2)
    (?:(?<![2x])part3)
    
  • 操作员必须在零件之间

    操作员不能是第一位或最后一位

    (?:(?<!^)OP(?!^))
    

    操作员不能相邻,要确保第二个操作员前面紧跟着part1或part2,这是最简单的测试,这使得“不在开始时”变得多余。

    (?:(?<=[2x])OP)
    

    为了保持一致,可以将第一位操作员的“不是从一开始”更改为“必须是part1”。

    (?:(?<=2)OP)
    

现在可以给我们了(显示在多行上可以澄清):

(?!$)
(?:part1)?
(?:(?<=2)OP(?!^))?
(?:(?<!2)part2)?
(?:(?<=[2x])OP(?!^))?
(?:(?<![2x])part3)?

全部结合在一起,并添加了捕获组以捕获(带符号的)数字和运算符

(?!$)(?:(-?\d*)x\^2)?(?:(?<=2)\s*([+-])\s*(?!-|^))?(?:(?<!2)(-?\d*)x)?(?:(?<=[2x])\s*([+-])\s*(?!-|^))?(?:(?<![2x])(-?\d+))?

这里是用Java编码的逻辑,用于在公式a中查找bcax^2 + bx + c

public static void main(String[] args) {
    System.out.println("part1 op1   part2 op2   part3   a  b  c  input");
    test("3x^2 + 4x + 5");
    test("x^2 + x + 1");
    test("x^2 - 4x");
    test("-x^2 - 1");
    test("-4x - 5");
    test("-3x^2");
    test("-4x");
    test("-5");
    test("");
    test("-3x^2 + -1x");
}
private static void test(String input) {
    String regex = "(?!$)" +
                   "(?:(-?\\d*)x\\^2)?" +
                   "(?:(?<=2)\\s*([+-])\\s*(?!-|^))?" +
                   "(?:(?<!2)(-?\\d*)x)?" +
                   "(?:(?<=[2x])\\s*([+-])\\s*(?!-|^))?" +
                   "(?:(?<![2x])(-?\\d+))?";
    Matcher m = Pattern.compile(regex).matcher(input);
    if (! m.matches()) {
        System.out.printf("%-41s\"%s\"%n", "No match", input);
    } else {
        String part1 = m.group(1);
        String op1   = m.group(2);
        String part2 = m.group(3);
        String op2   = m.group(4);
        String part3 = m.group(5);
        long a = parse(null, part1);
        long b = parse(op1, part2);
        long c = parse((op2 != null ? op2 : op1), part3);
        System.out.printf("%-6s%-6s%-6s%-6s%-6s%3d%3d%3d  \"%s\"%n",
                          (part1 == null ? "" : '"' + part1 + '"'),
                          (op1   == null ? "" : '"' + op1   + '"'),
                          (part2 == null ? "" : '"' + part2 + '"'),
                          (op2   == null ? "" : '"' + op2   + '"'),
                          (part3 == null ? "" : '"' + part3 + '"'),
                          a, b, c, input);
    }
}
private static long parse(String operator, String signedNumber) {
    long number;
    if (signedNumber == null)
        number = 0;
    else if (signedNumber.isEmpty())
        number = 1;
    else if (signedNumber.equals("-"))
        number = -1;
    else
        number = Long.parseLong(signedNumber);
    if ("-".equals(operator))
        number = -number;
    return number;
}

输出

part1 op1   part2 op2   part3   a  b  c  input
"3"   "+"   "4"   "+"   "5"     3  4  5  "3x^2 + 4x + 5"
""    "+"   ""    "+"   "1"     1  1  1  "x^2 + x + 1"
""    "-"   "4"                 1 -4  0  "x^2 - 4x"
"-"   "-"               "1"    -1  0 -1  "-x^2 - 1"
            "-4"  "-"   "5"     0 -4 -5  "-4x - 5"
"-3"                           -3  0  0  "-3x^2"
            "-4"                0 -4  0  "-4x"
                        "-5"    0  0 -5  "-5"
No match                                 ""
No match                                 "-3x^2 + -1x"

答案 1 :(得分:1)

尝试一下:

((-?\d+)x\^2\s*[+-]\s*)?(\d+)x\s*([+-]\s*\d+)
  • (-?\d+)x\^2\s*[+-]\s*)?
    • -?\d+-0或1个-符号,后跟一个或多个数字
    • x\^2-x字符,^字符,2个字符
    • \s*-可选空间
    • [+-]-+字符或-字符
    • ?-该组中的0或1。二次公式可能没有第一部分。删除此?,使其不可选
  • (\d+)x-一个或多个数字,后跟x个字符(例如2x)
  • \s*-可选空间
  • ([+-]\s*\d+)
    • [+-]-+字符或-字符
    • \s*-可选空间
    • \d+-一个或多个数字(例如3)