我可以设置一个 Func<>带有运行时变量的函数以省略将它们作为 C# 中的参数传递?

发布于 2024-08-15 17:19:47 字数 696 浏览 3 评论 0 原文

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

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

我在运行时计算 a、b、c、d 的值,并希望将以下等效项作为 Func 传递代码>.我可以在其中设置 X 的值,并获取 Y。

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

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

我意识到这可以通过传入一个双精度数组来完成,如下所示: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。

I have a numerical analysis program which for simplicity calculates an algorithm similar to:

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

I calculate the values of a,b,c,d at runtime and would like to pass the following equivalent as a Func<double, double>. Where I can set a value for X, and get Y.

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

Where 12,13,14,15 are the numbers calculated at runtime.

I realise this can be done by passing in a double array, like so: Func<double[], double>
but I am trying to avoid passing around the constants (which can be many).

Is there any way to set these numbers in a func at runtime?

(Preferably without making the calculation of a,b,c,d part of the Func<> itself? The calculation of a,b,c,d is 80% of the work)

E.g.:

a = ...

b = ...

c = ...

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

For every evaluation of ABCD - I will evaluate 10 x's.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

海拔太高太耀眼 2024-08-22 17:19:47

我不确定我是否完全明白你在问什么,但你也许可以尝试这样的事情?

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 来执行你的变量计算。

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

I'm not sure if I understand quite what you are asking, but you could try something like this, perhaps?

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;
}

In this case, you can just make a call to the CreateCalculationFunc(), which will do the heavy calculations once, and return a reusable Func<double,double> for doing your variable calculations.

Of course, this is extensible to any amount of pre-calculated constants and more than one variable.

人事已非 2024-08-22 17:19:47

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

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;
    }
}

Can't you create a class that contains your calculation (Func<double,double>) method that has properties for your "constants". Then you set the properties and use a reference to the Calculate method as your Func<double,double> delegate:

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;
    }
}
放低过去 2024-08-22 17:19:47

这听起来像是您想要函数式语言所谓的“柯里化”或“部分应用程序”。

给定一个 Func,您将一一应用这些值并减少参数集。

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

签名的函数

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

将产生一个带有您可以传递的

。 C# 中柯里化/部分应用程序的相关链接:

或者 - 尝试一下 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<...> 的东西),但这也应该是可能的。

这样,您就可以像今天一样预先计算一次,但您可以将函数范围缩小到每个消费者的最后一部分。

This sounds like you'd want what the functional languages call "currying" or "partial application".

Given a Func<a, b, c, d, x, result> you'd apply the values one by one and reduce the parameter set.

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

would result in a function with the signature

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

which you can pass on.

Relevant links for currying/partial application in C#:

Or - give F# a try ;)

Edit: A short code sample, created from the reference sites above:

Boilerplate code:

    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);
    }

Your Code:

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 is now a new Func that "knows" the preapplied values and can be passed around as you like. I couldn't find a readymade solution for delegates with more than 4 parameters (i.e. things that don't fit a Func<...>), but that should be possible as well.

This way you're precalculating once and just the way you do it today, but you can narrow down the function to the last part for every consumer.

鹿童谣 2024-08-22 17:19:47

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

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

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

There are several different Func<> overloads, you can use one with 5 generic parameters, with the first one being a KeyValuePair:

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

So you pass a and b as the kvp and c,d and x as the other parameters.

悸初 2024-08-22 17:19:47

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

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

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

    return Algorithm;
}

但只是对 Func<> 有点困惑和动作>>因为这是我第一次使用它们!感谢您的帮助。

In hindsight I could actually just do this;

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

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

    return Algorithm;
}

But was just a little confused by Func<> and Action<> as it was my first time using them! Thanks for your help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文