1

我有一个数值分析程序,为简单起见计算类似于:

y = ax^3 + bx^2 + cx + d;

我在运行时计算 a,b,c,d 的值,并希望将以下等价物作为 a 传递Func<double, double>。我可以在哪里为 X 设置一个值,然后得到 Y。

y = 12x^3 + 13x^2 + 14x + 15; 

其中 12,13,14,15 是运行时计算的数字。

我意识到这可以通过传入一个双数组来完成,如下所示:Func<double[], double> 但我试图避免传递常量(可能很多)。

有没有办法在运行时在 func 中设置这些数字?

(最好不要让 Func<> 本身的 a,b,c,d 部分的计算?a,b,c,d 的计算是工作的 80%)

例如:

a = ...

b = ...

c = ...

Func<x, double> {
     ((const)a) * x^3 +   ((const)b) * x^2 +   ((const)c) * x + 15;
}`

对于 ABCD 的每次评估 - 我将评估 10 个 x。

4

5 回答 5

11

我不确定我是否完全理解你的要求,但你可以尝试这样的事情,也许?

Func<double, double> CreateCalculationFunc()
{
    double a = heavy calculation;
    double b = heavy calculation;
    double c = heavy calculation;
    double d = heavy calculation;

    Func<double, double> calculation = (x) =>
    {
        // You can use the constants in here without passing them as parameters
        return x * (a * b / c - d);
    };

    return calculation;
}

在这种情况下,您只需调用CreateCalculationFunc(),它将执行一次繁重的计算,并返回一个可重用Func<double,double>的用于进行变量计算。

当然,这可以扩展到任何数量的预先计算的常量和多个变量。

于 2009-12-24T08:23:02.230 回答
2

您不能创建一个包含您的计算(Func<double,double>)方法的类,该方法具有“常量”的属性。然后设置属性并使用对该Calculate方法的引用作为Func<double,double>委托:

public class Calculator
{
    public double A { get; set; };
    public double B { get; set; };
    public double C { get; set; };
    public double D { get; set; };

    public double Calculate(double x)
    {
        return A*x*x*x + B*x*x + C*x + D;
    }
}
于 2009-12-24T08:13:53.580 回答
2

这听起来像你想要函数式语言所说的“currying”或“partial application”。

给定一个Func<a, b, c, d, x, result>,您将一个一个地应用这些值并减少参数集。

Func<a, b, c, d, x, result>(valueOfA)

会产生一个带有签名的函数

Func<b, c, d, x, result>

你可以传递。

C#中currying/partial application的相关链接:

或者 - 试试 F# ;)

编辑:一个简短的代码示例,从上面的参考站点创建:

样板代码:

    public static Func<B, R> Partial<A, B, R>(this Func<A, B, R> f, A a) {
        return b => f(a, b);
    }

    public static Func<B, C, R> Partial<A, B, C, R>(this Func<A, B, C, R> f, A a) {
        return (b, c) => f(a, b, c);
    }

    public static Func<B, C, D, R> Partial<A, B, C, D, R>(this Func<A, B, C, D, R> f, A a) {
        return (b, c, d) => f(a, b, c, d);
    }

您的代码:

Func<double, double, double, double, double> yourCalculation = (a, b, c, x) => a*Math.Pow(x, 3) + b*Math.Pow(x, 2) + c*x;

var aDefined = yourCalculation.Partial(12);
var bDefined = aDefined.Partial(13);
var cDefined = bDefined.Partial(14);

cDefined 现在是一个新的 Func,它“知道”预先应用的值,并且可以随意传递。我无法为超过 4 个参数的代表找到现成的解决方案(即不适合 Func<...> 的东西),但这也应该是可能的。

这样,您就可以按照今天的方式预先计算一次,但是您可以将功能缩小到每个消费者的最后一部分。

于 2009-12-24T08:39:21.190 回答
0

有几种不同的 Func<> 重载,您可以使用带有 5 个泛型参数的重载,第一个是KeyValuePair

Func<KeyValuePair<double,double>,double,double,double,double>

因此,您将 a 和 b 作为 kvp 并将 c、d 和 x 作为其他参数传递。

于 2009-12-24T08:14:02.410 回答
0

事后看来,我实际上可以这样做;

Class {
    a = ...
    b = ...

    Func Algorithm = (x) => {
        return x*a + x*b;
    }

    return Algorithm;
}

但是对 Func<> 和 Action<> 有点困惑,因为这是我第一次使用它们!谢谢你的帮助。

于 2009-12-27T21:13:24.580 回答