什么是设计数学解析器的最聪明方式?我指的是一个函数,它接受一个数学字符串(如:"2 + 3 / 2 + (2 * 5)"),并返回计算后的值。我很久以前在VB6中写过一个,但它最终变得过于臃肿,而且不太可移植(或聪明...)。欢迎提供一般性想法、伪代码或实际代码。
什么是设计数学解析器的最聪明方式?我指的是一个函数,它接受一个数学字符串(如:"2 + 3 / 2 + (2 * 5)"),并返回计算后的值。我很久以前在VB6中写过一个,但它最终变得过于臃肿,而且不太可移植(或聪明...)。欢迎提供一般性想法、伪代码或实际代码。
我知道这篇文章比较旧,但是在我开发一个大型应用程序中的计算器时,我遇到了一些问题,并尝试使用被接受的答案。这些链接对于理解和解决这个问题非常有帮助,因此不应该被忽视。 我正在使用Java编写Android应用程序,并为"string"表达式中的每个项目实际上将一个String存储在ArrayList中,当用户在小键盘上输入时。 对于中缀转后缀的转换,我迭代了ArrayList中的每个String,然后计算新排列的后缀ArrayList中的值。 对于少量操作数/运算符而言,这非常棒,但长时间的计算结果往往不准确,特别是当表达式开始评估为非整数时。 在中缀转后缀转换提供的链接中,它建议如果扫描的项是运算符且topStack项具有更高的优先级,则弹出堆栈。 我发现这几乎是正确的。如果顶部堆栈项的优先级高于或等于扫描的运算符,则弹出topStack项最终使我的计算结果正确。 希望这能帮助正在解决这个问题的任何人,并感谢Justin Poliey(以及fas?)提供了一些宝贵的链接。
开发者总是希望采用简洁的方法,并尝试从头开始实现解析逻辑,通常最终会采用Dijkstra Shunting-Yard Algorithm。结果是干净漂亮的代码,但可能存在漏洞。我已经开发了这样一个API,JMEP,它可以完成所有这些工作,但花费我多年时间才有稳定的代码。
即使经过那么多工作,你仍然可以看到甚至在那个项目页面上,我也在认真考虑转而使用JavaCC或ANTLR,即使已经完成了所有这些工作。
ANTLR是一个非常好的LL(*)解析器生成器。我强烈推荐它。
距离这个问题被提出已经过去了11年:如果您不想重复造轮子,那么有许多异国情调的数学解析器可供选择。
我多年前写了一个支持算术运算、方程求解、微积分、统计学基础、函数/公式定义、绘图等功能的解析器。
它名为ParserNG,并且是免费的。
评估表达式就像这样简单:
MathExpression expr = new MathExpression("(34+32)-44/(8+9(3+2))-22");
System.out.println("result: " + expr.solve());
result: 43.16981132075472
或者使用变量和计算简单表达式:
MathExpression expr = new MathExpression("r=3;P=2*pi*r;");
System.out.println("result: " + expr.getValue("P"));
或者使用函数:
MathExpression expr = new MathExpression("f(x)=39*sin(x^2)+x^3*cos(x);f(3)");
System.out.println("result: " + expr.solve());
result: -10.65717648378352
或者在给定点处求导数(注意它在幕后进行符号微分(而不是数值微分),因此精度不受数值逼近误差的限制):
MathExpression expr = new MathExpression("f(x)=x^3*ln(x); diff(f,3,1)");
System.out.println("result: " + expr.solve());
result: 38.66253179403897
我将为您翻译内容,这是关于编程的。在x=3处对x^3 * ln(x)
进行一次求导。现在可以进行的求导次数为1。
或者针对数值积分:
MathExpression expr = new MathExpression("f(x)=2*x; intg(f,1,3)");
System.out.println("result: " + expr.solve());
result: 7.999999999998261... approx: 8