Mathematical function differentiation with C#?

后端 未结 5 1784
旧时难觅i
旧时难觅i 2020-12-05 03:57

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 tha

相关标签:
5条回答
  • 2020-12-05 04:00

    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.

    0 讨论(0)
  • 2020-12-05 04:11

    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".

    0 讨论(0)
  • 2020-12-05 04:16

    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

    0 讨论(0)
  • 2020-12-05 04:17

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 04:24

    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);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题