class CubicSplineInterpolation { private: std::vector x; // 存储插值点横坐标 std::vector y; // 存储插值点纵坐标 std::vector h; // 存储每个小区间的步长 std::vector a; // 存储三次样条函数的系数a std::vector b; // 存储三次样条函数的系数b std::vector c; // 存储三次样条函数的系数c std::vector d; // 存储三次样条函数的系数d

public: // 构造函数,传入插值点横坐标和纵坐标 CubicSplineInterpolation(const std::vector& _x, const std::vector& _y) { if (_x.size() != _y.size()) throw std::invalid_argument("The sizes of x and y must be the same."); x = _x; y = _y; int n = x.size(); h.resize(n - 1); a.resize(n); b.resize(n); c.resize(n - 1); d.resize(n - 1); for (int i = 0; i < n - 1; i++) h[i] = x[i + 1] - x[i]; // 利用Thomas算法求解三次样条函数的系数 std::vector alpha(n - 1); std::vector beta(n - 1); alpha[0] = beta[0] = 0; for (int i = 1; i < n - 1; i++) { alpha[i] = h[i - 1] / (h[i - 1] + h[i]); beta[i] = (3 * (y[i + 1] - y[i]) / h[i] - 3 * (y[i] - y[i - 1]) / h[i - 1]) / (h[i - 1] + h[i]); } alpha[n - 1] = beta[n - 1] = 0; std::vector c_prime(n); std::vector l(n); std::vector mu(n); std::vector z(n); l[0] = 1; mu[0] = z[0] = 0; for (int i = 1; i < n - 1; i++) { l[i] = 2 - alpha[i] * mu[i - 1]; mu[i] = alpha[i] / l[i]; z[i] = (beta[i] - alpha[i] * z[i - 1]) / l[i]; } l[n - 1] = 1; z[n - 1] = c_prime[n - 1] = 0; for (int i = n - 2; i >= 0; i--) { c_prime[i] = z[i] - mu[i] * c_prime[i + 1]; c[i] = (3 * (y[i + 1] - y[i]) / h[i] - 2 * c_prime[i] - c_prime[i + 1]) / h[i]; d[i] = (c_prime[i + 1] + c_prime[i] - 2 * (y[i + 1] - y[i]) / (h[i] * h[i])) / (h[i] * h[i]); a[i] = y[i]; b[i] = (y[i + 1] - y[i]) / h[i] - h[i] * (2 * c_prime[i] + c_prime[i + 1]) / 3; } a[n - 1] = y[n - 1]; b[n - 1] = c[n - 1] = d[n - 1] = 0; }

// 根据横坐标x计算插值函数的纵坐标
double operator()(const double x_val) {
    int n = x.size();
    int i = 0;
    while (i < n - 1 && x[i + 1] <= x_val)
        i++;
    double t = (x_val - x[i]) / h[i];
    double y_val = a[i] + b[i] * t + c[i] * std::pow(t, 2) + d[i] * std::pow(t, 3);
    return y_val;
}

}

写一段三次样条插值函数的c++类库

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

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