【问题标题】:Evaluating mathematical expressions with custom script functions使用自定义脚本函数评估数学表达式
【发布时间】:2017-10-04 15:44:53
【问题描述】:

我正在寻找一种算法或方法来评估以字符串形式表示的数学表达式。该表达式包含数学组件,但也包含自定义函数。我希望在 C#/.Net 中实现上述算法。

我知道 Roslyn 允许我评估这种表达式

"var value = 3+5*11-Math.Sqrt(9);"

我也熟悉如何使用“节点重写”来避免变量声明或完全限定的函数名称或省略尾随分号以评估

"value = 3+5*11-Sqrt(9)"

但是,我想在此基础上实现的是提供自定义脚本功能,例如

"value = Ratio(A,B)",其中 Ratio 是一个自定义函数,它将向量 A 中的每个元素除以向量 B 中的每个元素,并返回相同长度的向量。

"value = Sma(A, 10)",其中 Sma 是一个自定义函数,用于计算向量/时间序列 A 的简单移动平均值,回溯窗口为 10。

理想情况下,我希望能够提供更多复杂性,例如

"value = Ratio(A,B) * Pi + 0.5 * Spread(C,D) + Sma(E, lookback)",解析引擎将尊重运算符优先级并构建解析树以获取值,以评估表达式。

我不知道如何用 Roslyn 解决这种问题。

还有哪些其他方法可以帮助我入门,或者我是否缺少 Roslyn 提供的可能有助于解决此问题的功能?

【问题讨论】:

  • 看看github.com/mariuszgromada/MathParser.org-mXparser。它满足您的所有要求,除了基本的方程求解外,它还包括添加用户定义函数/常量/参数等的能力,并支持许多内置函数。就像Function ratio = new Function("ratio(x,y) = x/y"); f.calculate(1,2); Expression e = new Expression("Ratio(A,B) * Pi + 0.5 * Spread(C,D) + Sma(E, lookback)", f); 一样简单。 Pi 已经定义好了!
  • 谢谢,去看看
  • 除了关于 mXparser 的提示 - 阅读 mXparser 教程:mathparser.org/mxparser-tutorial
  • 谢谢,我最终选择了 Roslyn,因为它提供了我需要的一切。

标签: c# .net roslyn string-parsing mathematical-expressions


【解决方案1】:

假设您的所有表达式都是有效的 C# 表达式,您可以通过多种方式使用 Roslyn。

  1. 您只能使用 Roslyn 进行解析。 SyntaxFactory.ParseExpression 会给你一个表达式的语法树。请注意,您的第一个 (var v = expr;) 示例不是表达式,而是变量声明。然而v = expr 是一个表达式,即AssignmentExpressionSyntax。然后你可以遍历这个 AST,对每个节点做你想做的事情,基本上你会写一个解释器。这种方法的好处是您不必编写自己的解析器,遍历 AST 非常简单,而且这种方法很灵活,因为定义您使用“未知”方法做什么完全取决于您。

  2. 也使用 Roslyn 进行评估。这可以通过多种方式完成:或者将有效的 C# 文件放在一起,然后将其编译到程序集中,或者您可以通过 Scripting API。这种方法基本上需要一个类库,其中包含所有额外方法的实现,例如SmaSpread,......但在第一种方法中也需要以某种形式,所以它并不是真正的额外方法努力。

如果唯一的目标是评估表达式,那么我会采用第二种方法。如果有额外的要求(你没有提到)比如能够生成一个简化形式的表达式,那么我会考虑第一个解决方案。

  1. 如果您找到了一个完全符合您需要的库(并且性能很好,而且您不介意对第 3 方工具的依赖,...),我会同意的。评论中建议的MathParser.org-mXparser 似乎正是您想要的。

【讨论】:

  • 太好了,我想我需要进一步了解 Roslyn 的语法树功能。
猜你喜欢
  • 2010-12-05
  • 1970-01-01
  • 2011-02-08
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 2011-06-30
相关资源
最近更新 更多