[英]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
如果您不反對 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.