我正在寻找一种算法或方法来评估以字符串形式表示的数学表达式。表达式包含数学组件以及自定义函数。我希望在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提供的可能有助于解决此问题的功能?
答案 0 :(得分:4)
假设您的所有表达式都是有效的C#表达式,您可以通过多种方式使用Roslyn。
您只能使用Roslyn进行解析。 SyntaxFactory.ParseExpression
会为您提供表达式的语法树。请注意,您的第一个(var v = expr;
)示例不是表达式,而是变量声明。但是v = expr
是一个表达式,即AssignmentExpressionSyntax
。然后你可以遍历这个AST,并对每个节点做你想做的事情,基本上你会写一个解释器。这种方法的好处是你不必编写自己的解析器,走一个AST非常简单,这种方法很灵活,因为定义你用“未知”方法做的事情将完全取决于你。 / p>
也可以使用Roslyn进行评估。这可以通过多种方式完成:将有效的C#文件放在一起,然后将其编译到程序集中,或者可以浏览Scripting API。这种方法基本上需要一个类库,其中包含所有额外方法的实现,例如Sma
,Spread
,......但是在第一种方法中也需要某些形式,所以它是不是真正的额外努力。
如果唯一的目标是评估表达式,那么我会采用第二种方法。如果有额外的要求(你没有提到),比如能够说出表达的简化形式,那么我会考虑第一个解决方案。
MathParser.org-mXparser
似乎正是您所寻找的。