TL; DR
如何使用系数数组构建表达式并将其转换为Func< int,double>?有比表达树更好的方法吗?
我有一个不可变的序列类型,使用Func< int,double>构造用于为序列A生成术语An的公式.我开始构建一个辅助类,用一些简单的参数构造常见的数学公式:
public static Sequence CreateLinearSequence (double m,double b)
{ return new Sequence (n => m * n + b); }
我为常量序列,对数和简单多项式(线性,二次,三次和四次)构建了标准方法,但我想使用params关键字扩展它以支持任意数量的项.
这是我的方法:
public static Sequence CreatePolynomialSequence (params double[] coeff)
{
Expression<Func<int,double>> e = x => 0;
double pow = 0;
for (int i = coeff.Length - 1; i >= 0; i--)
{
double c = coeff[i];
var p = Expression.Parameter (typeof (int),"x");
e = Expression.Lambda<Func<int,double>> (
Expression.Add (
e,(Expression<Func<int,double>>)(x => c * Math.Pow (x,pow))
),p);
pow++;
}
return new Sequence (e.Compile ());
}
对你们这些人来说,我做错了可能是显而易见的;我搞砸了一下,直到我得到了一些我觉得应该工作的东西,但事实并非如此.
目标是使序列像这样工作一个数组double [] coeff = {a,b,c,d,e,f,g,h}
x => h gx fx ^ 2 ex ^ 3 dx ^ 4 cx ^ 5 bx ^ 6 ax ^ 7使用适当的Math.Pow(x,exponent)调用.
运行
var s2 = SequenceHelper.CreatePolynomialSequence (new[] { 1d,2 });
Console.WriteLine ("s2: " + s2);
结果是
Unhandled Exception: System.InvalidOperationException: The binary
operator Add is not defined for the types
‘System.Func2[System.Int32,System.Double]' and
'System.Func
2[System.Int32,System.Double]’. at
System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow
(ExpressionType binaryType,System.String name,
System.Linq.Expressions.Expression left,
System.Linq.Expressions.Expression right,Boolean liftToNull)
[0x0004a] in
/private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:658
at System.Linq.Expressions.Expression.Add
(System.Linq.Expressions.Expression left,System.Reflection.MethodInfo
method) [0x00057] in
/private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:1409
at System.Linq.Expressions.Expression.Add
(System.Linq.Expressions.Expression left,
System.Linq.Expressions.Expression right) [0x00000] in
/private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:1390
at Sequence.SequenceHelper.CreatePolynomialSequence (System.Double[]
coeff) [0x00110] in
/Users/Knoble/MonoProjects/Sequences/Sequence/SequenceHelper.cs:88
at Sequence.Test.Main () [0x0001f] in
/Users/Knoble/MonoProjects/Sequences/Sequence/Test.cs:53 [ERROR]
FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: The
binary operator Add is not defined for the types
‘System.Func2[System.Int32,
System.Linq.Expressions.Expression right) [0x00000] in
/private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:1390
at Sequence.SequenceHelper.CreatePolynomialSequence (System.Double[]
coeff) [0x00110] in
/Users/Knoble/MonoProjects/Sequences/Sequence/SequenceHelper.cs:88
at Sequence.Test.Main () [0x0001f] in
/Users/Knoble/MonoProjects/Sequences/Sequence/Test.cs:53 The
application was terminated by a signal: SIGHUP
我对问题和所有三个答案感到困惑;如果您打算将它们编译成委托,那么为什么要搞乱表达式树呢?直接返回代表!
public static Func<double,double> CreatePolynomialFunction (params double[] coeff)
{
if (coeff == null) throw new ArgumentNullException("coeff");
return x =>
{
double sum = 0.0;
double xPower = 1;
for (int power = 0; power < coeff.Length; power += 1)
{
sum += xPower * coeff[power];
xPower *= x;
}
return sum;
};
}
完成.不要乱用表达树.
(我注意到我假设数组中的第n个项目是第n个系数;显然你在数组中向后列出你的系数.这似乎容易出错,但是如果这就是你想要的那么那么修改这个答案并不困难将循环从Length-1运行到零.)