作为计算Jordan正规形式矩阵的个人项目的一部分,我发现我需要解析具有复系数的多项式,以便简化许多代码。
(帖子底部的相关代码)
我想解析的多项式具有以下形式:
+
或-
开头。1
不会出现,只会出现符号。+
。x
可能具有幂(>2
),可能具有1的幂,然后它显示为x
,或者可能根本不显示。正确格式化多项式的一些例子:
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
。
相关代码在文件中:
PolyParser.java
Polynomial.java
Complex.java
测试单元位于文件PolyParserTest.java
。
答案 0 :(得分:1)
正则表达式基本上无法解析表达式,因为它们无法跟踪嵌套(例如括号)。这是大多数人不知道的教训,他们发现这很难。
但是,使用自上而下的解析,表达式很容易解析。请参阅我的答案,了解如何执行此操作:schema.org此答案涵盖了如何进行解析,并链接到另一个答案,该答案讨论如何构建AST来表示表达式。
第一步:编写一个表示你的表达式允许的语法。你的问题中有一个特别的描述,但语法会强迫你写出它合法和不合法的内容。使用该语法,您可以非常轻松地编写上面建议的递归下降解析器。