7

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?

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Rogez Sanchez
  • 225
  • 1
  • 3
  • 8
  • I think you mean "differentiation." Do you want it done numerically? Do you really mean to use ints as the return type and parameters instead of floats? – Corey Dec 16 '08 at 23:47
  • float or double, it was just an example of what I would like to do. – Rogez Sanchez Dec 16 '08 at 23:48
  • You need to rewrite your question. I have read it several times and still don't get exactly what you are asking. From the answers, I can see I am not the only one with this problem. – Jason Jackson Dec 17 '08 at 01:30

5 Answers5

41

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);
        }
    }
}
Rawling
  • 49,248
  • 7
  • 89
  • 127
isekaijin
  • 19,076
  • 18
  • 85
  • 153
  • 1
    Very consise and simple explanation of Numerical Differentiation in C#. Thanks :) – Dr. Andrew Burnett-Thompson Aug 18 '11 at 11:45
  • @Andrew Burnett-Thompson: Thanks. – isekaijin Aug 18 '11 at 11:52
  • Could you please demonstrate how to use this? – LaRiFaRi Aug 16 '13 at 13:54
  • 1
    @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 a `double`, 2. construct a `Function`, passing the method you previously created as its delegate argument, 3. construct a `Derivative`, passing the `Function` you previously created as its argument. – isekaijin Aug 16 '13 at 15:19
  • @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. – sdjuan Sep 04 '16 at 07:58
  • 1
    @sdjuan: To call an `IFunction`, use the operator `[]`, as if you were indexing an array. – isekaijin Sep 04 '16 at 12:03
  • Forgive my ignorance, what type is x representing? imaginary Number? String? Double? Tuple? – Rusty Nail Jan 25 '18 at 00:22
  • 1
    Apologies: Double, the arg variable is x two different methods. – Rusty Nail Jan 25 '18 at 00:38
7

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

ntownsend
  • 7,462
  • 9
  • 38
  • 35
1

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;
        }
    }
}
Natalie Perret
  • 8,013
  • 12
  • 66
  • 129
1

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.

Chris Brandsma
  • 11,666
  • 5
  • 47
  • 58
0

If you have written the function, it's already been derived.

And given that it's an int function, I'll assume you don't mean the calculus definition of "derive".

recursive
  • 83,943
  • 34
  • 151
  • 241