Java - 使用正则表达式

时间:2015-09-29 12:45:52

标签: java regex parsing polynomials

作为计算Jordan正规形式矩阵的个人项目的一部分,我发现我需要解析具有复系数的多项式,以便简化许多代码。

(帖子底部的相关代码)

我想解析的多项式具有以下形式:

  1. 系数可以是实数,虚数或复数。
  2. 如果系数很复杂,它将用括号括起来。如果这些括号是领先系数,则不会以+-开头。
  3. 如果系数是实数,虚数或复数,其实数和\或虚数分量为1,则1不会出现,只会出现符号。
  4. 括号前面只有+
  5. 变量x可能具有幂(>2),可能具有1的幂,然后它显示为x,或者可能根本不显示。
  6. 关于多项式的文本表示没有更多规则,即权力不一定按升序或降序排列。
  7. 正确格式化多项式的一些例子:

    • 1
    • -1
    • -2.1x
    • 3i
    • x^2-1
    • -x^3+2x+1
    • (5-5i)x^2-x-1
    • (-1+i)x-5
    • -ix^3-x^2+1

    ..和一些格式不合理的:

    • 1x(引导不必要的1
    • +(+1-2i)x(括号中有一个前导+,实际组件有前导+
    • (5.1i)x^2(因为系数是假想的,所以不需要括号)
    • -(i-1)(复杂系数具有领先-

    经过一些在线阅读(SO,Java教程,Java API)之后,我很快得出结论,考虑到上面提到的所有限制,正则表达式是解析的最简单方法。 在正式方面,这个任务的正则表达式是可能的,因为我画了一个NFA只接受这样的有效表达式。

    我正在做这个TDD(通过JUnit 4),这个测试失败了:

    assertEquals("Polynomial parsed incorrectly.", poly07, PolyParser.parse(exp07));

    其中poly07如下所示:(5-5i)x^2-x-1

    这是被引发的例外:

    java.lang.NumberFormatException: For input string: "5-5"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
    at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
    at java.lang.Double.parseDouble(Double.java:538)
    at PolyParser.parse(PolyParser.java:55)
    at PolyParserTest.testParse(PolyParserTest.java:59)
    

    我尝试过调试,看到正则表达式捕获5-5i(后来剥离了i)。然后它尝试使用参数字符串Double.parseDouble调用5-5,这会导致异常。

    在完成所有阅读之后,我无法弄清楚正则表达式中所需的调整是什么,以便整个节目能够正常工作。 此外,正则表达式不像上面提到的表示限制那样排序,因为我想在尝试将其解析为真实之前查看系数是否复杂;也遇到了实数(即带小数点)被解析为整数的问题,这就是正则表达式首先处理实数的原因。

    正则表达式:

    public static final String POLYNOMIAL_REGEX =
            "([+-])?" +                     // leading plus or minus
            "(\\()?" +                      // parenthesis to denote the beginning of a complex number
            "([+-])?(((\\d+.\\d+)|\\d+)i)?" +      // component of coefficient, imaginary
            "(((-)?\\d+.\\d+)|\\d+)?" +     // component of coefficient, real
            "(\\))?" +                      // parenthesis to denote the end of a complex number
            "(x)?" +                        // variable
            "(?:\\^(\\d+))?";               // power of the variable
    

    我不会在这里发布所有相关代码,因为它会混淆东西。所有代码都在GitHub上,请务必切换到分支PolyParser

    相关代码在文件中:

    1. PolyParser.java
    2. Polynomial.java
    3. Complex.java
    4. 测试单元位于文件PolyParserTest.java

1 个答案:

答案 0 :(得分:1)

正则表达式基本上无法解析表达式,因为它们无法跟踪嵌套(例如括号)。这是大多数人不知道的教训,他们发现这很难。

但是,使用自上而下的解析,表达式很容易解析。请参阅我的答案,了解如何执行此操作:schema.org此答案涵盖了如何进行解析,并链接到另一个答案,该答案讨论如何构建AST来表示表达式。

第一步:编写一个表示你的表达式允许的语法。你的问题中有一个特别的描述,但语法会强迫你写出它合法和不合法的内容。使用该语法,您可以非常轻松地编写上面建议的递归下降解析器。