簡體   English   中英

使用 Math.NET C# 計算導數

[英]Calculating a derivative with Math.NET C#

我正在尋找一個簡單的函數,它將接受一個 double 值數組並返回數學導數。

Math.NET 似乎有這樣的函數,但它要求以下語法:

double FirstDerivative(Func<double, double> f, double x)

我不確定為什么我需要指定一個函數。 我只想要一個可以將數據傳遞給的預先存在的函數。

獲取您的數據點並創建一個 Math.NET Numerics Cubic Spline對象。 然后使用.Differentiate()方法獲取您想要的每個點的斜率。

例子

試試下面的代碼:

static class Program
{
    const int column_width = 12;
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        var xvec = new DenseVector(new double[] { 0.0, 1.0, 2.0, 3.0, 4.0 });
        var yvec = new DenseVector(new double[] { 3.0, 2.7, 2.3, 1.6, 0.2 });
        Debug.WriteLine("Input Data Table");
        Debug.WriteLine($"{"x",column_width} {"y",column_width}");
        for(int i = 0; i < xvec.Count; i++)
        {
            Debug.WriteLine($"{xvec[i],column_width:G5} {yvec[i],column_width:G5}");
        }
        Debug.WriteLine(" ");
        var cs = CubicSpline.InterpolateNatural(xvec, yvec);

        var x = new DenseVector(15);
        var y = new DenseVector(x.Count);
        var dydx = new DenseVector(x.Count);
        Debug.WriteLine("Interpoaltion Results Table");
        Debug.WriteLine($"{"x",column_width} {"y",column_width} {"dy/dx",column_width}");
        for(int i = 0; i < x.Count; i++)
        {
            x[i] = (4.0*i)/(x.Count-1);
            y[i] = cs.Interpolate(x[i]);
            dydx[i] = cs.Differentiate(x[i]);
            Debug.WriteLine($"{x[i],column_width:G5} {y[i],column_width:G5} {dydx[i],column_width:G5}");
        }


    }
}

並查看調試輸出:

Input Data Table
           x            y
           0            3
           1          2.7
           2          2.3
           3          1.6
           4          0.2

Interpoaltion Results Table
           x            y        dy/dx
           0            3     -0.28214
     0.28571        2.919     -0.28652
     0.57143       2.8354     -0.29964
     0.85714       2.7469      -0.3215
      1.1429       2.6509     -0.35168
      1.4286       2.5454     -0.38754
      1.7143        2.429     -0.42864
           2          2.3       -0.475
      2.2857        2.154     -0.55809
      2.5714       1.9746      -0.7094
      2.8571       1.7422     -0.92894
      3.1429       1.4382      -1.1979
      3.4286       1.0646      -1.4034
      3.7143      0.64404      -1.5267
           4          0.2      -1.5679

情節1

如果您不反對 Math.Net 以外的庫,則可以嘗試AlgLib及其spline1ddiff函數

構建樣條曲線很容易,而且 Akima 樣條曲線通過點看起來很好且平滑。 如果你想要一個方法來接收一組數據並返回導數,這里有一個使用 AlgLib 數學庫的例子:

public static void CalculateDerivatives(this Dictionary<double, double> inputPoints, out Dictionary<double, double> firstDerivatives, out Dictionary<double, double> secondDerivatives)
{
        var inputPointsXArray = inputPoints.Keys.ToArray();
        var inputPointsYArray = inputPoints.Values.ToArray();

        spline1dinterpolant akimaSplineToDifferentiate;
        alglib.spline1dbuildakima(inputPointsXArray, inputPointsYArray, out akimaSplineToDifferentiate);

        firstDerivatives = new Dictionary<double, double>();
        secondDerivatives = new Dictionary<double, double>();
        foreach (var pair in inputPoints)
        {
            var xPoint = pair.Key;
            double functionVal, firstDeriv, secondDeriv;
            alglib.spline1ddiff(akimaSplineToDifferentiate, xPoint, out functionVal, out firstDeriv, out secondDeriv);

            firstDerivatives.Add(point, firstDeriv);
            secondDerivatives.Add(point, secondDeriv);
        }
}

警告:Akima Spline 在數據集范圍之外具有不可預測的行為。

感謝您的回復。

我相信我需要遍歷數組,從 Math.NET 調用 Differentiate 函數,或者可能只是編寫我自己的(運行時上升)計算。

在這里你有函數的衍生擴展

public static Func<double[], double> Derivative(this Func<double[], double> func, int derivativeIndex)
{
    double step = 0.001;
    return income => 
    {
        double[] increasedIncome = (double[])income.Clone();
        increasedIncome[derivativeIndex] += step;

        double[] decreasedIncome = (double[])income.Clone();
        decreasedIncome[derivativeIndex] -= step;

        return (func(increasedIncome) - func(decreasedIncome)) / (2 * step);
    };
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM