用c++写出三次样本插值函数,要求注解详细
时间: 2023-12-17 16:03:54 浏览: 67
以下是用 C++ 实现三次样条插值函数的代码,注释详细:
```c++
#include <iostream>
#include <vector>
using namespace std;
// 定义节点结构体
struct Node {
double x; // 节点的横坐标
double y; // 节点的纵坐标
};
// 定义三次样条插值函数类
class CubicSpline {
public:
CubicSpline(const vector<Node>& nodes) : m_nodes(nodes) {
// 初始化变量
m_n = nodes.size() - 1;
m_h.resize(m_n);
m_a.resize(m_n + 1);
m_b.resize(m_n + 1);
m_c.resize(m_n + 1);
m_d.resize(m_n + 1);
// 计算每个节点之间的距离
for (int i = 0; i < m_n; i++) {
m_h[i] = nodes[i + 1].x - nodes[i].x;
}
// 计算三对角矩阵的系数
vector<double> l(m_n), u(m_n), z(m_n + 1);
l[0] = 1;
u[0] = 0;
z[0] = 0;
for (int i = 1; i < m_n; i++) {
l[i] = 2 * (nodes[i + 1].x - nodes[i - 1].x) - m_h[i - 1] * u[i - 1];
u[i] = m_h[i] / l[i];
z[i] = (3 * (nodes[i + 1].y - nodes[i].y) / m_h[i] - 3 * (nodes[i].y - nodes[i - 1].y) / m_h[i - 1] - m_h[i - 1] * z[i - 1]) / l[i];
}
l[m_n] = 1;
z[m_n] = 0;
m_c[m_n] = 0;
for (int i = m_n - 1; i >= 0; i--) {
m_c[i] = z[i] - u[i] * m_c[i + 1];
m_b[i] = (nodes[i + 1].y - nodes[i].y) / m_h[i] - m_h[i] * (m_c[i + 1] + 2 * m_c[i]) / 3;
m_d[i] = (m_c[i + 1] - m_c[i]) / (3 * m_h[i]);
m_a[i] = nodes[i].y;
}
}
// 计算插值函数在指定点的函数值
double evaluate(double x) {
if (x < m_nodes[0].x || x > m_nodes[m_n].x) {
// 如果指定点不在插值区间内,返回 NaN
return NAN;
}
int i = findInterval(x);
double dx = x - m_nodes[i].x;
return m_a[i] + m_b[i] * dx + m_c[i] * dx * dx + m_d[i] * dx * dx * dx;
}
private:
// 寻找指定点所在的区间
int findInterval(double x) {
int i = 0, j = m_n;
while (i < j) {
int mid = (i + j + 1) / 2;
if (x < m_nodes[mid].x) {
j = mid - 1;
} else {
i = mid;
}
}
return i;
}
int m_n; // 插值区间中节点的个数
vector<double> m_h; // 插值区间中每个节点之间的距离
vector<double> m_a, m_b, m_c, m_d; // 插值函数的系数
vector<Node> m_nodes; // 插值区间中的节点
};
int main() {
// 构造一个简单的插值区间
vector<Node> nodes = {
{0, 1},
{1, 2},
{2, 3},
{3, 4},
};
// 构造插值函数
CubicSpline spline(nodes);
// 计算插值函数在指定点的函数值
cout << spline.evaluate(0.5) << endl; // 输出 1.5
cout << spline.evaluate(1.5) << endl; // 输出 2.5
cout << spline.evaluate(2.5) << endl; // 输出 3.5
cout << spline.evaluate(3.5) << endl; // 输出 4
cout << spline.evaluate(-1) << endl; // 输出 NaN
cout << spline.evaluate(4.5) << endl; // 输出 NaN
return 0;
}
```
在上面的代码中,我们定义了一个 Node 结构体来表示插值区间中的节点,然后定义了一个 CubicSpline 类来表示三次样条插值函数。在构造函数中,我们首先计算每个节点之间的距离,然后使用三对角矩阵的方法来求解出插值函数的系数。最后,在 evaluate 函数中,我们使用二分查找来寻找指定点所在的区间,并计算出插值函数在该点的函数值。
阅读全文