解析
- ラグランジュ補間法
離散的なデータから連続的なデータを近似して得たい場合に補間法が用いられます。ここでは最も基本的なアルゴリズムとしてラグランジュ補間法を紹介しています。
ラグランジュ補間法には以下のような特徴があります。
・多項式近似であるため両端で発散する
・データ数が多い場合に大きな誤差を伴うことがある
というわけですから、実用としてはお勧めしません。プログラミング学習用として紹介させていただきます。
計算には以下の式を用います。(証明略)
f(x) : 得られた連続データ
x : 連続データの変数
y : 離散変数
xi,xj : 離散変数
また、グラフの描画にはNPlotを使用しています。
public partial class FormLagrangeInterpolation : Form
{
private NPlot.Windows.PlotSurface2D _ploter;
private void FormLagrangeInterpolation_Load( object sender, EventArgs e )
{
// 補間前の離散的データ
double[] X = new double[ 4 ];
double[] Y = new double[ 4 ];
X[ 0 ] = 1; Y[ 0 ] = 60;
X[ 1 ] = 2; Y[ 1 ] = -10;
X[ 2 ] = 3; Y[ 2 ] = 8;
X[ 3 ] = 4; Y[ 3 ] = 30;
int nDataCount = 50;
double dWidth = 6.0 / (double)nDataCount;
double[] x = new double[ nDataCount ];
double[] Fx = new double[ nDataCount ];
for( int i = 0; i < nDataCount; i++ )
{
x[ i ] = dWidth * i;
Fx[ i ] = LagrangeInterpolation( X, Y, x[ i ] );
}
//--------------------------------------------------------------------------------
// コントロール生成
_ploter = new NPlot.Windows.PlotSurface2D();
this.Controls.Add( _ploter );
// 基本設定
_ploter.Clear();
_ploter.Title = "ラグランジュ補間";
_ploter.BackColor = Color.LightGray;
_ploter.PlotBackColor = Color.WhiteSmoke;
_ploter.ShowCoordinates = true;
_ploter.TitleColor = Color.Black;
_ploter.DateTimeToolTip = true;
// ドラッグによるビュー移動
_ploter.AddInteraction( new NPlot.Windows.PlotSurface2D.Interactions.HorizontalDrag() );
_ploter.AddInteraction( new NPlot.Windows.PlotSurface2D.Interactions.VerticalDrag() );
_ploter.AddInteraction( new NPlot.Windows.PlotSurface2D.Interactions.AxisDrag( true ) );
// レジェンド
NPlot.Legend legend = new NPlot.Legend();
legend.AttachTo( NPlot.PlotSurface2D.XAxisPosition.Top, NPlot.PlotSurface2D.YAxisPosition.Left );
legend.VerticalEdgePlacement = NPlot.Legend.Placement.Inside;
legend.HorizontalEdgePlacement = NPlot.Legend.Placement.Inside;
legend.YOffset = 8;
_ploter.Legend = legend;
_ploter.LegendZOrder = 1000;
// 補間前の離散的データ描画
NPlot.PointPlot rawData = new NPlot.PointPlot();
rawData.Label = "RawData";
rawData.Marker = new NPlot.Marker();
rawData.Marker.Filled = true;
rawData.Marker.Color = Color.Blue;
rawData.ShowInLegend = true;
rawData.OrdinateData = Y;
rawData.AbscissaData = X;
_ploter.Add( rawData );
// 補間後のデータ描画
NPlot.LinePlot interpolated = new NPlot.LinePlot();
interpolated.Label = "Interpolated";
interpolated.ShowInLegend = true;
interpolated.Color = Color.Green;
interpolated.OrdinateData = Fx;
interpolated.AbscissaData = x;
_ploter.Add( interpolated );
// 表示更新
_ploter.Refresh();
}
/// <summary>ラグランジュ補間法</summary>
/// <param name="X">補間前離散的データX</param>
/// <param name="Y">補間前離散的データY</param>
/// <param name="x">補間後データX</param>
/// <returns>補間後データY</returns>
public double LagrangeInterpolation( double[] X, double[] Y, double x )
{
if( X == null ) return 0;
if( Y == null ) return 0;
if( X.Length != Y.Length ) return 0;
// Π計算
double[] dPai = new double[ X.Length ];
for( int i = 0; i < X.Length; i++ )
{
double dNumerator = 1.0;
double dDenominator = 1.0;
for( int j = 0; j < X.Length; j++ )
{
if( i == j ) continue;
dNumerator *= x - X[ j ];
dDenominator *= X[ i ] - X[ j ];
}
dPai[ i ] = dNumerator / dDenominator;
}
// Σ計算
double dSigma = 0.0;
for( int i = 0; i < Y.Length; i++ )
{
dSigma += Y[ i ] * dPai[ i ];
}
return dSigma;
}
}