/****************函数说明*********************/
//px py为已知的数据点,xs为要插值的x坐标,最终会得到xs坐标下的y值
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace spline
{
class Program
{
writeline函数 static void Main(string[] args)
{
point[] points = new point[13];
double[] px = { 64, 304, 544, 1035, 1502, 2061, 2540, 2939, 3498, 3897, 4456, 4696, 4936 };
double []py={4.663,4.476,4.969,4.853,4.766,5.2415,4.795,4.7055,5.4565,5.5515,5.411,5.8385,6.7085};
for (int i = 0; i < 13; i++)
{
points[i] = new point();
points[i].x =px[i];
points[i].y = py[i];
}
point.DeSortX(points);
double[] xs = {64, 304, 544, 1023, 1502, 1981, 2460, 2939, 3418, 3897, 4376, 4616, 4856};
splineInsertPoint(points, xs, 1);
Console.ReadLine();
}
static double[] splineInsertPoint(point[] points, double[] xs, int chf)
{
int plength = points.Length;
double[] h = new double[plength];
double[] f = new double[plength];
double[] l = new double[plength];
double[] v = new double[plength];
double[] g = new double[plength];
//三转角法的待定一阶系数法。基本方程为l(i)m(i-1)+2m(i)+u(i)m(i+1)=g(i),i=1,2,...,n-1
//目前有n-1个方程,n+1个未知量(从m0到mn),需要添加两个边界条件
for (int i = 0; i < plength - 1; i++) //共有plength(n+1)个点,h总有plength-1(n)个值
{
h[i] = points[i + 1].x - points[i].x;
}
for (int i = 1; i < plength - 1; i++)
{
l[i] = h[i] / (h[i - 1] + h[i]);
v[i] = h[i - 1] / (h[i - 1] + h[i]);
g[i] = 3 * (l[i] * f[i - 1] + v[i] * f[i]); //i=1,2,3,...,n-1
}
//求解矩阵,用追赶法
double[] U = new double[plength]; //上三角矩阵U ,plength=n+1阶矩阵
double[] L = new double[plength]; //下三角矩阵L
double[] m = new double[plength]; //用于保存m0-mn的一阶系数数值
double[] Y = new double[plength]; //中间矩阵Y
/***********************矩阵分界,求解待定的一阶系数,m1到m(n-1)*************************/
U[0] = 2;
v[0] = 1;
for (int i = 1; i < plength;i++ )
{
L[i] = l[i] / U[i-1];
U[i] = 2 - v[i - 1] * L[i];
}
Y[0] = g[0];
for(int i = 1; i < plength;i++)
{
Y[i] = g[i] - L[i] * Y[i - 1];
}
m[plength - 1] = Y[plength - 1] / U[plength - 1];
for(int i = plength - 2; i>=0; i--)
{
m[i] = (Y[i] - v[i] * m[i + 1]) / U[i];
}
/*****************************************************************************************/
int xlength = xs.Length; //记录需要插值的点的个数
double[] insertRes = new double[xlength]; //用于返回插值点的Y坐标
for (int i = 0; i < xlength; i++)
{
int j = 0;
for (j = 0; j < plength; j++)
{
if (xs[i] < points[j].x)
break;
}
j = j - 1;
//Console.WriteLine(j); //表示要插值的点数组的坐标在第j+1组区间
if (j == -1 || j == plength - 1)
{
if (j == -1)
throw new Exception("插值下边界超出");
if (j == plength - 1 && xs[i] == points[j].x)
//这种情况是,需要插值的点正好等于一系列点x坐标最大的那个点
insertRes[i] = points[j].y;
else
throw new Exception("插值下边界超出");
}
else
{
//根据每个分段的三次多项式求值
insertRes[i] = (h[j]+2*(xs[i]-points[j].x))*Math.Pow(xs[i]-points[j+1].x,2)*points[j].y/Math.Pow(h[j],3) + (h[j]+2*(points[j+1].x-xs[i]))*Math.Pow(xs[i]-points[j].x,2)*points[j+1].y/Math.Pow(h[j],3) + (xs[i]-points[j].x)*Math.Pow(xs[i]-points[j+1].x,2)*m[j]/Math.Pow(h[j],2) + (xs[i]-points[j+1].x)*Math.Pow(xs[i]-points[j].x,2)*m[j+1]/Math.Pow(h[j],2);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论