song.yz@foxmail.com wechat: math-box

计算数学



Hermit插值

有些实际问题,不仅要求插值多项式在插值点与函数值相同,而且还要求导数相同, 这类问题就是Hermit插值问题。

如果 f(x)在区间[a,b]上连续可以导,x0,x1,xn[a,b]是互异的, 那么存在唯一的多项式 H2n+1(x)满足多项式在这些点上的值与函数 f(x)的值相等、 多项式在这些点的一阶导数值与函数的一阶导数值相等。

这个多项式可以表示为 H2n+1(x)=i=0nf(xi)[12(xxi)li(xi)]li2(x)+i=0nf(xi)(xxi)li2(x) 其中 li(x)=j=0jin(xxi)(xixj),i=0,1,,n li(xi)=j=0jin1xixj,i=0,1,,n 这就是Hermite插值。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
class chermite
/*--------------------------------------class comment
 Version   :  V1.0
 Coded by  :  syz
 Date      :  2011-07-16 22:31:09          *星期六*
----------------------------------------------------
Desciption : Hermite插值
 *
parameters :
 *  fout-----------输出文件对象
 *
Methods    :
 *  Hermite--------插值方法
 *  Hermite--------对一点的插值方法
 *  drive----------驱动函数
 *
--------------------------------------------------*/
{
    public StreamWriter fout = new StreamWriter("fout.txt");
    public VEC hermite(VEC x, VEC y, VEC dy, VEC xx)
    /*------------------------------------------ comment
    Author      : syz
    Date        : 2011-07-16 22:32:24
    ---------------------------------------------------
    Desciption  : Hermite插值方法
     *
    Post Script :
     *
    paramtegers :
     *  x--------样本自变量
     *  y--------样本应变量
     *  dy-------样本导数值
     *  xx-------待插值点
     *  返回值--------插值结果(维数同xx)
    -------------------------------------------------*/
    {
        //获取要插值数据向量的维数
        int M = xx.dim;

        //声明yy为新的向量并分配地址
        VEC yy=new VEC(M);

        for (int i = 0; i < M; i++)
            yy[i] = hermite0(x, y, dy,xx[i]);

        return yy;

    }
    public double hermite0(VEC x, VEC y, VEC dy, double xx)
    /*------------------------------------------ comment
    Author      : syz
    Date        : 2011-07-16 22:33:41
    ---------------------------------------------------
    Desciption  : 对单点的插值方法
     *
    Post Script :
     *
    paramtegers :
     *   x-------样本自变量
     *   y-------样本应变量
     *   dy------样本导数值
     *   xx------要插值点
     *   返回值-------插值结果
    -------------------------------------------------*/
    {
        //获取x的维数
        int N = x.dim;

        //声明L和dL并分配地址
        VEC L=new VEC(N);
        VEC dL=new VEC(N);

        //该段循环求得L
        for (int i = 0; i < N ; i++)
        {
            L[i] = 1.0;
            for (int j = 0; j < N; j++)
            {
                //如果j和i相等,退出当前循环,
                //但并不退出循环体
                if (j == i)
                    continue;

                L[i] = L[i] * (xx - x[j]) / (x[i] - x[j]);

            }

        }
        //该段循环求得dL
        for (int i = 0; i < N; i++)
        {
            dL[i] = 0;
            for (int j = 0; j < N; j++)
            {
                if (j == i)
                    continue;
                dL[i] = dL[i]+1.0 / (x[i] - x[j]);
            }
        }
        double  yy=0;
        for (int i = 0; i < N; i++)
            yy = yy + y[i] * (1.0 - 2.0* (xx - x[i]) *
             dL[i]) * L[i] * L[i]
                + dy[i] * (xx - x[i]) * L[i] * L[i];
        //返回计算结果
        return yy;
    }
}