问题
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.
回答1:
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.
回答2:
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;
}
}
回答3:
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#:
- http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx
- http://blogs.msdn.com/sriram/archive/2005/08/07/448722.aspx
- http://www.c-sharpcorner.com/UploadFile/rmcochran/Curry01122008102239AM/Curry.aspx
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.
回答4:
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.
回答5:
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.
来源:https://stackoverflow.com/questions/1957312/can-i-set-a-func-function-with-runtime-variables-to-omit-passing-them-as-param