Mathematical function differentiation with C#?
Solution 1
You can't calculate the exact derivative of a function using a computer program (unless you're doing symbolic math... but that's another, way more complicated, topic).
There are several approaches to computing a numerical derivative of a function. The simplest is the centered three-point method:
- Take a small number h
- Evaluate
[f(x+h) - f(x-h)] / 2h
- Voilà, an approximation of f'(x), with only two function evaluations
Another approach is the centered five-point method:
- Take a small number h
- Evaluate
[f(x-2h) - 8f(x-h) + 8f(x+h) - f(x+2h)] / 12h
- Voilà, a better approximation of f'(x), but it requires more function evaluations
Another topic is how to implement this using C#. First, you need a delegate that represents a function that maps a subset of the real numbers onto a another subset of the real numbers:
delegate double RealFunction(double arg);
Then, you need a routing that evaluates the derivative:
public double h = 10e-6; // I'm not sure if this is valid C#, I'm used to C++
static double Derivative(RealFunction f, double arg)
{
double h2 = h*2;
return (f(x-h2) - 8*f(x-h) + 8*f(x+h) - f(x+h2)) / (h2*6);
}
If you want an object-oriented implementation, you should create the following classes:
interface IFunction
{
// Since operator () can't be overloaded, we'll use this trick.
double this[double arg] { get; }
}
class Function : IFunction
{
RealFunction func;
public Function(RealFunction func)
{ this.func = func; }
public double this[double arg]
{ get { return func(arg); } }
}
class Derivative : IFunction
{
IFunction func;
public static double h = 10e-6;
public Derivative(IFunction func)
{ this.func = func; }
public double this[double arg]
{
get
{
double h2 = h*2;
return (
func[arg - h2] - func[arg + h2] +
( func[arg + h] - func[arg - h] ) * 8
) / (h2 * 6);
}
}
}
Solution 2
If you're thinking of symbolic manipulation of formulae then you're better off doing your derivations in languages like Maple or Mathematica. They're designed for symbolic computation.
EDIT: If Maple and Mathematica are too expensive for you then there are other options. Wikipedia has a fairly complete listing of computer algebra packages. http://en.wikipedia.org/wiki/Comparison_of_computer_algebra_systems
Solution 3
Are you thinking of Lambda Expressions?
Basically you can pass a function into a function.
So think of a Sort on an object. Depending on the nature of the object would help determine how the objects are sorted.
But you can still create a generic sort function then pass in how to compare objects.
Solution 4
Another approach can be to leverage the extensions methods using the well-known definition of the derivative number and compute its approximation accordingly.
As it has already been mentioned, this is pretty easy for a numeric approach not a symbolic one:
public partial static class IEnumerableExtensions
{
public static IEnumerable<Double> Derivate1<TSource>(this IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
{
var enumerator = source.GetEnumerator();
enumerator.Reset();
enumerator.MoveNext();
var itemPrevious = enumerator.Current;
var itemNext = default(TSource);
while (enumerator.MoveNext())
{
itemNext = enumerator.Current;
var itemPreviousX = selectorX(itemPrevious);
var itemPreviousY = selectorY(itemPrevious);
var itemNextX = selectorX(itemNext);
var itemNextY = selectorY(itemNext);
var derivative = (itemNextY - itemPreviousY) / (itemNextX - itemPreviousX);
yield return derivative;
itemPrevious = itemNext;
}
}
}
or if you are more into a foreach
fashion
public partial static class IEnumerableExtensions
{
public static IEnumerable<Double> Derivate2<TSource>(IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
{
var itemPrevious = source.First();
source = source.Skip(1);
foreach (var itemNext in source)
{
var itemPreviousX = selectorX(itemPrevious);
var itemPreviousY = selectorY(itemPrevious);
var itemNextX = selectorX(itemNext);
var itemNextY = selectorY(itemNext);
var derivative = (itemNextY - itemPreviousY) / (itemNextX - itemPreviousX);
yield return derivative;
itemPrevious = itemNext;
}
}
}
You can refactor everything as below:
public static partial class MathHelpers
{
public static Double Derivate(Double xPrevious, Double xNext, Double yPrevious, Double yNext)
{
var derivative = (yNext - yPrevious)/(xNext - xPrevious);
return derivative;
}
}
public static class IEnumerableExtensions
{
public static IEnumerable<Double> Derivate<TSource>(IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
{
var itemPrevious = source.First();
source = source.Skip(1);
foreach (var itemNext in source)
{
var derivative = MathHelpers.Derivate(selectorX(itemPrevious), selectorX(itemNext), selectorY(itemPrevious), selectorY(itemNext));
yield return derivative;
itemPrevious = itemNext;
}
}
}
Rogez Sanchez
Updated on July 23, 2022Comments
-
Rogez Sanchez almost 2 years
I see that I can declare a function with (say)
public double Function(double parameter)
but what if I do want to take the derivative of that function?
-
Rogez Sanchez over 15 yearsYes this is what I would like. Create a function and manipulate it. I need a third party?
-
ntownsend over 15 yearsThe verbal form of the derivative operation in calculus is 'differentiate', not 'derive'.
-
B Bulfin over 15 yearsAh. Duly noted. Learning. I like it.
-
Dr. Andrew Burnett-Thompson over 12 yearsVery consise and simple explanation of Numerical Differentiation in C#. Thanks :)
-
pyon over 12 years@Andrew Burnett-Thompson: Thanks.
-
LaRiFaRi over 10 yearsCould you please demonstrate how to use this?
-
pyon over 10 years@LaRiFaRi: Sorry, my C# is rusty these days, I am more of a Haskell and ML programmer. But here is the general idea: 1. make a regular method that takes a
double
and returns adouble
, 2. construct aFunction
, passing the method you previously created as its delegate argument, 3. construct aDerivative
, passing theFunction
you previously created as its argument. -
sdjuan over 7 years@pyon: that looks interesting but like LaRiFaRi I'd like to see an example. What you described in answer to LaRiFaRi seems like a text description of the 3 parts of the object version you posted in your answer. I can easily implement that object version you describe but I have no clue how to actually call that to get a derivative back from it. Thanks.
-
pyon over 7 years@sdjuan: To call an
IFunction
, use the operator[]
, as if you were indexing an array. -
Rusty Nail over 6 yearsForgive my ignorance, what type is x representing? imaginary Number? String? Double? Tuple?
-
Rusty Nail over 6 yearsApologies: Double, the arg variable is x two different methods.