原文连接(http://www.singularsys.com/jep/doc/html/index.html)
介绍
综述
Jep 是一个用于分析和计算数学表达式的java库。有了这个包,您就可以把数学公式当作是字符串,并且立即求出它们的值。许多常见的数学函数和常量都是内置的,可以直接使用。但是,您还可以通过自定义变量、常量和函数来扩充Jep。
特征
- 小巧(仅有 218KB 的 jar 归档)
- 求值快
- 支持任意精度的算法
- 支持字符串、向量和复数
- 包含常见的数学函数和预定义的常量
- 支持布尔表达式(!, &&, ||, <, >, !=, ==, >=, 和 <=)
- 支持隐式乘法(允许使用如“3x”这样的表达式代替“3*x”)
- 支持赋值表达式(x = 5)
- 允许在声明和未声明变量之间进行选择
- 通过用户自定义的函数可扩展
- 可定制的语法表达式
- 兼容J2SE 5
- 支持Unicode字符(包括希腊符号)
- 大量的文档
- 包括 JavaCC 语法
解释和求值
用Jep来求解字符串表达式是一个两步过程,如下图所示。首先,解释表达式,将它从字符串表示转换成树形表示。树形表示是表达式的结构化表示,它允许在第二步中对表达式进行简单快速的计算。下面的部分将更加详细地讨论这两个步骤。
解析
我们可以用一般的术语来描述解析,即把一系列字符作为输入,并生成包含在该组字符中的信息的结构化表示。这里的重点是数学表达式,尽管解析也用于其他领域,例如自然语言解析。
数学公式可以用树数据结构来表示,数字、变量、操作符和函数都用数的节点来表示。数字和变量由所谓的子节点表示,而运算符和函数由父节点表示。父节点在子节点之上运行。例如,表达式“1+2*3”可以表示成一个有5个节点的树,如上所示。
您可能会问为什么乘法节点是加法节点的子节点。其原因是操作符的优先级。操作符有一个优先顺序,在解释表达式时需要遵循。乘法的优先级比加法的优先级高。所以,在上面的例子中,我们需要先将2和3相乘,再将结果加1。在树中,这被表示成将数字2和3作为乘操作的子元素。最后,乘法节点自身所为加法节点的子节点,表示乘法的结果被用作加法运算。语法分析器负责按照语法中指定的优先顺序执行。
语法分析器通常使用语法分析生成程序生成,例如JavaCC,ANTLR,Sablecc,Yacc或Bison。Jep中的一些例程是用JavaCC(https://javacc.dev.java.net/)生成的。JavaCC使用在JccParser.jjt文件中定义的语法,创建了一组类来执行解释过程的核心任务。还包括一个可配置的纯java解释器。
求值
求值使表达式从树形表示到表达式的值。由于树是根据操作符的优先级构建的,所以求值的方法不需要知道操作符的优先级。可以使用简单的方法来遍历树,以确定表达式的值。
一个简单的方法是从根节点(最顶层结点)开始,并应用递归的方法。这可以通过访问者设计模式实现。可以为每个节点类型创建不同的方法。要求一个操作符结点或函数结点的值,首先要求其子节点的值。然后,使用子节点的值来确定节点本身的值。对于那些是常量(数字)或变量的节点,节点计算的是常量或变量的值。使用这种递归方法,树将以深度优先的方式快速遍历。