具有无序变量特性的Java公式评估库

10

我目前正在寻找一个Java库(或带有Java API的本地库)用于公式解析和计算。

根据这里的建议,我研究了许多库:

  • JFormula
  • JEval
  • Symja
  • JEP

但是它们都不能满足我的需求,我的需求是:

  • 多个公式之间具有依赖关系的公式计算(公式总是将其他变量或数字值分配给变量)
  • 能够仅更改其中一个公式而不影响其他50个公式,并且具有良好的性能
  • 无需手动处理变量依赖关系
  • 如果公式更改,则自动更新其他相关变量
  • 能够监听哪些变量发生了变化
  • 无需为变量指定特定格式(用户将直接输入名称,不想使用复杂符号)

也许举个例子会更好。 假设我们按照以下顺序将其输入到系统中:

  • a = b + c
  • c = 2 * d
  • b = 3
  • d = 2

我希望能够以这种顺序输入这4行,并要求得出“a”的结果(或“b”,无论哪个)。 然后,如果在用户界面(基本上是一个表变量<>公式)中将“b”更改为“2 * d”,该库将自动更改“b”和“a”的值,并返回(或启动事件或调用函数)一系列变化的列表

最好的库就像JEP一样,但具有无顺序的变量功能和自动评估相关变量的可能性

我知道编译器和电子表格软件使用这种机制,但我没有找到任何Java或Java兼容的库可以直接使用。

有人知道这样的库吗?

编辑:精度:问题实际上是关于一个库,或者最终要链接在一起的一组库。这个问题是为了一个公司的项目,想法是尽可能少地花费时间。 "自己动手做" 的解决方案已经得到评估,并不在问题的范围内。


所以你正在尝试解决同时方程 - user207421
一个快速的方法是编写一个简单的解析器来识别每个方程式中的每个标记,从而确定一个方程式对其他方程式的依赖关系。这将使您能够按正确的顺序将它们注入到JEP中。 - Farid
谢谢!但是我们希望避免手动解析和依赖的实现。 - cporte
也许我没有正确解释观点 :). 自己做并不是技术问题,如果没有可用的库,那么就会这样做。但是所有关于项目管理、技术控制、测试、科学验证等方面的额外工作都是一种痛苦(不要问为什么,你真的不想知道^^)。 - cporte
@cporte,听起来你在一个可怕的地方工作。但是为什么会出现这样的不一致呢?为什么你不应该严格测试和验证你正在使用的任何外部库呢? - SK-logic
显示剩余4条评论
5个回答

1
对于我需要一个简单的公式解析器的项目,我使用了javaworld.com上的文章词法分析,第2部分:构建应用程序中的代码。它很简单且小巧(7个类),您可以根据自己的需求进行调整。
您可以从这里下载源代码(搜索“词法分析第二部分”条目)。

0

不知道有任何库。

假设您拥有的是一组方程,其中至少一个方程的一侧具有单个变量(不允许A + B = C-D),并且没有循环(例如,A = B + 1; B = A-2),则您需要做的技术上是构建一个数据流图,显示每个运算符如何依赖其操作数。对于无副作用的方程(例如,纯数学),这非常容易;您最终会得到一个有向无环图(表示共享子表达式的共享子树的森林)。然后,如果更改了变量的值或引入了新公式,则需要修改dag并重新评估已更改的部分,将更改传播到dag的根。因此,您需要为表达式构建树,然后共享它们(通常通过哈希子树来查找潜在的等效候选项)。因此,需要进行大量的结构操作以保持dag(及其根值)。

但是,如果只有50个变量的复杂性,您可以简单地重新评估它们所有。如果将表达式存储为树(或更好的是逆波兰式),则可以相当快地评估每个树,并且您不需要支付任何开销来保持所有这些数据结构最新。

如果你有数百个方程式,dag方案可能更好。

如果你有约束方程式(例如,不限制两侧的内容),你已经超出了电子表格模型,进入了约束求解器,这是一种更复杂的技术。


谢谢你的回答!但我真的在寻找一个库。我们知道如何实现它,但我们没有资源来设计、实现、测试、调试等等,只有在没有其他解决方案时才会这样做。 - cporte
“简单重新评估最多50个方程式”非常容易实现,只要您能够实现1个方程式,而这很容易。 - Ira Baxter

0

为什么不自己写呢?你对这项任务的复杂性的评估可能是错误的。实际上比你想象的要容易得多——很有可能,学习如何处理任何第三方库需要比从零开始实现这样的微不足道的东西需要更多的努力。在最坏的情况下,它不应该花费超过几个小时。

对于简单的事情来说,寻找第三方库没有任何意义(我知道,这是Java精神的一部分,但还是...)

我建议看看Cells库以获得灵感。它是用Common Lisp编写的,但其思想非常基本,可以转移到任何其他地方。


1
从技术上讲,现在它并不是真正的复杂...如果我们不使用第三方库,它将成为一个内部项目,并且会变成一场噩梦(管理层要畏惧!)。 我只是惊讶于没有好的第三方库存在,但所有的回复和评论似乎都表明这是事实。 这也是我限制问题范围的原因。我的问题不是“如何做到这一点?”,而是“是否有人已经完成并分享了它,因为我们这里有更有趣的事情要做” :) - cporte
1
@cporte,几百行代码怎么可能会变成噩梦?不必要的外部依赖始终是一场噩梦。这就是为什么你永远找不到一个足够通用的库来处理像这样微不足道的事情。 - SK-logic
再次强调,噩梦不在技术部分,但我们现在真的偏离主题了。再次感谢您的回复,我完全理解您的观点(顺便说一句,我完全同意您的观点,也许除了“永远找不到一个可用的库”,因为只需要在JEP上花费一些努力就可以使其准备好)。如果您有空闲时间和动力,也许您可以在这里提供一个“手工”解决方案的架构建议/概述,这对我和其他有相同需求的人总是有用的。无论如何,再次感谢! - cporte

0

0

我会嵌入Groovy,在这里可以查看关于嵌入的教程Freeplane(一个Java思维导图工具)也使用Groovy进行公式计算。

每当变量发生改变时,您必须将新值放入绑定中。 所有单元格代码都应作为单个代码段提供给Groovy Shell。 您可以通过BindPath注册更改。

无论如何,我假设您必须实现一个薄层以满足您的要求:

  • 不需要手动处理变量依赖性
  • 可以监听哪个变量已更改

越来越多的库正在嵌入Groovy,只是为了更轻松的配置(他们使用Groovy而不是XML)。Groovy 2.0已经被模块化以保持其大小。例如logback、maven 3 polyglot、Freeplane等。 - ChrLipp
难怪我们得到的代码超出了想象。有些人想要一个子程序,而建议是他包含整个子语言以获取一些他可能能够使用的功能。 - Ira Baxter
我们正在谈论JSR 223:Java平台的脚本编写 - http://www.jcp.org/en/jsr/detail?id=223 - http://groovy.codehaus.org/JSR+223+Scripting+with+Groovy - 但你肯定知道得更好。 - ChrLipp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接