我正在尋找一個可以將數學公式解析為AST(抽象語法樹)的Java庫。
更新:
我願意接受Java以外的其他語言,前提是我可以從Java調用這些工具/庫。例如,可以使用 Rhino引擎嵌入JavaScript。
基本要求:
-
以中綴表示法解析公式的功能。
-
保留未知變量的能力-我不是在尋找計算器。
-
可自定義的運算符和函數列表。 -in函數(例如
sin(x)
)。 ol>
非基本要求:
- 該庫可以是開源的,但不是必須的。一個免費的圖書館就足夠了。
我正在尋找一個可以將數學公式解析為AST(抽象語法樹)的Java庫。
更新:
我願意接受Java以外的其他語言,前提是我可以從Java調用這些工具/庫。例如,可以使用 Rhino引擎嵌入JavaScript。
基本要求:
以中綴表示法解析公式的功能。
保留未知變量的能力-我不是在尋找計算器。
可自定義的運算符和函數列表。 -in函數(例如 sin(x)
)。
非基本要求:
“ Math.js是JavaScript和Node.js的擴展數學庫。”
— 項目自述文件
它提供了 parse()函數。
使用NodeJS環境的示例:
var math = require('mathjs')(); var ast = math.parse('xy ^(1/2)'); / /完整記錄對象var util = require('util'); console.log(util.inspect(ast,{showHidden:false,depth:null}));
輸出:
{op:'^',fn:'pow',params:[{name:'xy'},{op:'/',fn:'divide',params:[{ valueType:'數字',值:'1'},{valueType:'數字',值:'2'}]}]}}
我使用 Java Nashorn VM(僅在Java> = 8中可用)執行JavaScript。
程序體系結構:
User- ------------- > Java輸入形式| ---- > Nashorn ---- > math.js | < ---------------- ----- |用戶< ----------------- |
使用Nashorn引擎非常簡單(省略了異常處理)
ScriptEngine引擎= new ScriptEngineManager()。getEngineBy Name(“ nashorn”); engine.eval(readerInstancePointingToMathJsLibrary); engine.eval(readerInstancePointingToBridgeJavaScript);
網橋的JavaScript代碼在很大程度上取決於AST節點的實現。我們利用Nashorn在JavaScript中創建Java對象並將其傳輸到Java的能力。示例:
var math = mathjs(); function convert(formula){var ast = math.parse(formula); var javaAst = / *使用Java對象構建AST * / return javaAst;}
我們現在可以從Java訪問該函數,甚至可以傳遞任意參數:
Invocable inv =(Invocable)引擎; //表達式是我在Javaexpr中的AST節點類型=(Expression)inv.invokeFunction(“ convert”,FormulaFromUser);
注意:我需要一種快速解析數學表達式的方法。解析器(手寫的或由解析器生成器生成的)始終是首選。儘管如此,上面的代碼顯示瞭如何輕鬆集成Java Nashorn。
幾個月前,我使用 Esprima來解析此類輸入。實際上,Esprima會解析任何JavaScript輸入(將其轉換為樹),因此它應適用於此類數學表達式。
包含Esprima後,您可以執行以下操作:
esprima .parse(input);
...,其中 input
是一個字符串,其中包含應解析的輸入(如果無效,則將引發錯誤) 。
示例
esprima.parse(“ 1 + 2 * 3”)
返回以下對象:
{“ type”:“ Program”,“ body”:[{“ type”:“ ExpressionStatement”,“ expression”:{“ type”:“ BinaryExpression”, “ operator”:“ +”,“ left”:{“ type”:“ Literal”,“ value”:1,“ raw”:“ 1”},“ right”:{“ type”:“ BinaryExpression”,“運算符”:“ *”,“左”:{“類型”:“文字”, “ value”:2,“ raw”:“ 2”},“ right”:{“ type”:“ Literal”,“ value”:3,“ raw”:“ 3”}}}}]}}
我修改了Esprima代碼,並將其用於一個實驗項目中,以在JavaScript中定義自定義運算符。該應用程序在GitHub上是開源的: http://ionicabizau.net/JavaScript-custom-operators/
似乎 JEP 是一個數學表達式解析器。
JEP是Java API用於解析和評估數學表達式。使用該庫,您可以允許用戶輸入任意公式作為字符串,並立即對其進行評估。 JEP支持用戶定義的變量,常量和函數。
功能
- 易於使用的軟件包,用於解析數學表達式
- 小尺寸(僅作為jar歸檔文件為56kb)
- 支持布爾表達式(!,&&,||,<,>,!=,==,> =和< =)
- 快速求值(可以快速評估表達式中的不同變量值)
- 包括常用的數學函數
- 可通過用戶定義的函數擴展
- 預定義常量,例如“ pi”和“ e'
- 支持字符串,複數和向量
- 支持隱式乘法(允許使用諸如“ 3x”而不是“ 3 * x”之類的表達式)
- 允許在已聲明和未聲明的變量之間進行選擇
- 與Java 1.1兼容(已通過Sun Java JDK 1.1.8和Microsoft Java VM測試)
- 支持Unicode字符(包括希臘符號) )
- 包括JavaCC語法,從中生成了n個類
它是 SourceForge上的開源代碼。
關於此主題還有一個SO問題: https://stackoverflow.com/q/4589951/1420197
構建公式解析器/樹構建器是一個非常簡單的練習。您可以尋找一個庫,但是您最終總是會對其進行修改以產生所需的庫。取而代之的是,簡單地編寫所需的代碼可能會更容易。
如果您想解析更多內容,可以使用它比表達式複雜,您可以推動這種解析器來執行此操作,但是在這種情況下,切換到解析器生成器通常更容易。
我已經使用javassist將Java表達式轉換為字節碼(如果要評估表達式,這可能是您最終要尋找的東西)。它甚至可以重新定義現有功能。