三次样条插值是一种用于数据内插或外推的数值方法,主要用于数据平滑和曲线拟合。下面是用C++实现三次样条插值的代码:

#include <iostream>
#include <cmath>
using namespace std;

const int MAXN = 100;
double x[MAXN], y[MAXN];
double a[MAXN], b[MAXN], c[MAXN], d[MAXN];

// 求解三次样条插值
void solve(int n)
{
    double h[MAXN], alpha[MAXN], l[MAXN], mu[MAXN], z[MAXN];

    for (int i = 1; i < n; i++) {
        h[i] = x[i] - x[i-1];
        alpha[i] = 3.0/h[i]*(y[i+1]-y[i])-3.0/h[i-1]*(y[i]-y[i-1]);
    }

    l[0] = 1.0; mu[0] = z[0] = 0.0;

    for (int i = 1; i < n-1; i++) {
        l[i] = 2.0*(x[i+1]-x[i-1])-h[i-1]*mu[i-1];
        mu[i] = h[i]/l[i];
        z[i] = (alpha[i]-h[i-1]*z[i-1])/l[i];
    }

    l[n-1] = 1.0; z[n-1] = c[n-1] = 0.0;

    for (int i = n-2; i >= 0; i--) {
        c[i] = z[i]-mu[i]*c[i+1];
        b[i] = (y[i+1]-y[i])/h[i]-h[i]*(c[i+1]+2.0*c[i])/3.0;
        d[i] = (c[i+1]-c[i])/(3.0*h[i]);
        a[i] = y[i];
    }
}

// 对插值结果进行输出
void output(int n)
{
    cout << '插值结果:' << endl;
    for (int i = 0; i < n-1; i++) {
        cout << 'x = ['' << x[i] << '', '' << x[i+1] << ''], ';
        cout << 'y = ' << a[i] << ' + ' << b[i] << '(x - ' << x[i] << ') + ';
        cout << c[i] << '(x - ' << x[i] << ')^2 + ' << d[i] << '(x - ' << x[i] << ')^3' << endl;
    }
}

int main()
{
    int n;
    cout << '请输入数据点的个数:';
    cin >> n;
    cout << '请输入数据点(x,y):' << endl;
    for (int i = 0; i < n; i++) {
        cin >> x[i] >> y[i];
    }
    solve(n);
    output(n);
    return 0;
}

在上面的代码中,我们首先输入了数据点的个数和数据点$(x_i,y_i)$,然后调用solve函数求解插值系数$a_i,b_i,c_i,d_i$,最后调用output函数输出插值结果。在输出插值结果时,我们采用分段函数的形式,对每一段$(x_i,x_{i+1})$都输出一个三次多项式的形式,其中$a_i,b_i,c_i,d_i$就是三次多项式的系数。

需要注意的是,上面的代码实现了三次样条插值的基本算法,但是并没有考虑插值的误差和精度问题。如果需要提高插值的精度,可以增加数据点的个数或者使用更高阶的多项式进行插值。


原文地址: https://www.cveoy.top/t/topic/lKRN 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录