什么是设计一个数学解析器的最聪明的方法是什么? 我的意思是一个函数,需要一个数学的字符串(如:“2 + 3/2 +(2 * 5)”),并返回计算值? 我的确写了一个在VB6年代久远,但它结束了办法臃肿,而不是非常便携(或智能为此事......)。 总体思路,伪代码或实际代码是表示赞赏。
Answer 1:
一个非常不错的方法将涉及两个步骤。 第一个步骤涉及从缀转换表达式为后缀 (例如,经由Dijkstra的调车场 )符号。 一旦这样做了,这是非常容易的编写一个后缀评估 。
Answer 2:
我写了几篇博客设计一个数学解析器。 有一种普遍的介绍 ,有关基本知识语法 , 样本实现用Ruby编写和测试套件 。 或许你会觉得这些材料有用。
Answer 3:
你有几个办法。 您可以生成动态代码,为了得到答案,而无需编写大量代码执行。 只是执行.NET运行时生成的代码搜索,并有大量的例子左右。
另外,您可以创建一个实际的解析器,并产生一点点解析树,然后用来计算表达式。 再次,这是基本的表情很简单。 看看CodePlex上,因为我相信他们有一个有数学解析器。 或者只是仰望BNF其中将包括实例。 任何网站介绍编译器的概念将包括此作为一个基本的例子。
Codeplex上表达式求值
Answer 4:
我知道这是老了,但我碰到这个来试图建立一个计算器作为一个更大的应用程序的一部分,并使用公认的答案遇到了一些问题跑了。 该环节得到理解和解决这个问题有极大的帮助,不应该被忽视。 我是用Java编写一个Android应用程序,并在表达式中的每个项目“串,”我实际上存储一个字符串在一个ArrayList作为键盘上的用户类型。 对于缀 - 后缀转换,我通过ArrayList中每个String迭代,然后评价字符串的新布置后缀的ArrayList。 这是梦幻般的少数操作数/运营商,但更长的计算是一致的了,尤其是在表达开始评估非整数。 在所提供的链接, 为后缀的转换中缀 ,它暗示出栈,如果扫描项目是一个运营商和topStack项目具有更高的优先级。 我发现,这几乎是正确的。 当弹出topStack项目,如果它的优先级高于或等于该扫描操作终于使我计算出来正确的。 希望这将帮助任何人在这个问题上的工作,并感谢贾斯汀Poliey(和Fas?)提供了一些宝贵的链接。
Answer 5:
如果你有一个“永远在线”的应用程序,只是张贴数学串谷歌和分析结果。 简单的方法,但不知道如果这就是你所需要的 - 但聪明的在某些方面我猜。
Answer 6:
相关问题方程(表达式)解析器与优先顺序? 对如何让这个开始还有一些有用的信息。
-亚当
Answer 7:
假设你的输入字符串格式的缀表达式,你可以将其转换为postfix的 ,并使用一对堆栈的:运营商栈和操作数堆栈,从那里工作的解决方案。 您可以在维基百科的链接一般算法的信息。
Answer 8:
ANTLR是一个很不错的LL(*)分析器发电机。 我高度推荐它。
Answer 9:
开发商总是希望有一个干净的方法,并尝试实施从根本上解析逻辑,通常与结束了Dijkstra算法调度场算法 。 结果是整齐看代码,但有可能进行的bug缠身。 我已经开发了这样的API, JMEP ,但这一切,但我花了几年有稳定的代码。
即使所有的工作,你甚至可以从我认真地考虑切换到使用的JavaCC或ANTLR该项目页面中看到,即使在所有的工作已经完成。
Answer 10:
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 * ln(x)
一次在x = 3。 你可以区分的次数为1现在。
或数值积分:
MathExpression expr = new MathExpression("f(x)=2*x; intg(f,1,3)");
System.out.println("result: " + expr.solve());
result: 7.999999999998261... approx: 8
这个解析器是体面的速度快,有很多其他的功能。
工作已经结束了对通过绑定目标C将它移植到斯威夫特和我们在绘图其中包括反复使用情况的应用程序中使用它。
免责声明:ParserNG是由我撰写。