使用Math.NET C#计算导数

我正在寻找一个简单的函数,它将接受一个double值数组并返回数学导数。

Math.NET似乎有这样的function,但它要求以下语法:

double FirstDerivative(Func f, double x) 

我不确定为什么我需要指定一个函数。 我只想要一个可以传递数据的预先存在的函数。

获取数据点并创建Math.NET Numerics Cubic Spline对象。 然后使用.Differentiate()方法获取所需的每个点的斜率。

请尝试以下代码:

 static class Program { const int column_width = 12; ///  /// The main entry point for the application. ///  [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 xy 0 3 1 2.7 2 2.3 3 1.6 4 0.2 Interpoaltion Results Table xy 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 

plot1

如果您不反对Math.Net以外的库,您可以尝试使用AlgLib及其spline1ddiff函数

构建样条曲线非常简单,Akima样条曲线看起来非常漂亮且平滑。 如果你想要一个接收一组数据并返回衍生物的方法,下面是一个使用AlgLib数学库的例子:

 public static void CalculateDerivatives(this Dictionary inputPoints, out Dictionary firstDerivatives, out Dictionary secondDerivatives) { var inputPointsXArray = inputPoints.Keys.ToArray(); var inputPointsYArray = inputPoints.Values.ToArray(); spline1dinterpolant akimaSplineToDifferentiate; alglib.spline1dbuildakima(inputPointsXArray, inputPointsYArray, out akimaSplineToDifferentiate); firstDerivatives = new Dictionary(); secondDerivatives = new Dictionary(); 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函数,或者简单地编写我自己的(up over run)计算。

这里有函数的衍生扩展

  public static Func Derivative(this Func 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); }; }