使用c++实现分别用 (1)基于拉格朗日插值法,利用线性插值和抛物线插值,求的近似值; (2)基于牛顿插值法(阅读课本P81-P84),利用线性插值和抛物线插值,求根号115的近似值; 要求:(a)利用程序自动选择在插值计算中所需要的节点;(b)把原始数据点以及得到的插值多项式函数曲线都绘制在MATLAB Figure里,便于观察插值效果。
时间: 2023-11-28 18:49:24 浏览: 94
以下是基于拉格朗日插值法和牛顿插值法的C++代码实现,包括自动选择节点和绘制曲线的功能。需要注意的是,本代码仅供参考,可能存在漏洞和不足,建议仔细阅读并自行测试验证。
```c++
#include <iostream>
#include <cmath>
#include <vector>
#include <fstream>
#include "mat.h" // MATLAB engine头文件
using namespace std;
// 拉格朗日插值法
double lagrange_interp(double x, vector<double>& x_data, vector<double>& y_data) {
double y = 0;
int n = x_data.size();
for (int i = 0; i < n; i++) {
double l = 1;
for (int j = 0; j < n; j++) {
if (j != i) {
l *= (x - x_data[j]) / (x_data[i] - x_data[j]);
}
}
y += l * y_data[i];
}
return y;
}
// 抛物线插值法
double parabolic_interp(double x, vector<double>& x_data, vector<double>& y_data) {
int n = x_data.size();
int i = 1;
while (i < n && x_data[i] < x) {
i++;
}
if (i == n) {
i--;
} else if (i > 1) {
if (fabs(x - x_data[i]) > fabs(x - x_data[i - 1])) {
i--;
}
}
double x1 = x_data[i - 1], x2 = x_data[i], x3 = x_data[i + 1];
double y1 = y_data[i - 1], y2 = y_data[i], y3 = y_data[i + 1];
double f1 = (y2 - y1) / (x2 - x1);
double f2 = ((y3 - y2) / (x3 - x2) - f1) / (x3 - x1);
double y = y2 + f1 * (x - x2) + f2 * (x - x2) * (x - x3);
return y;
}
// 牛顿插值法
double newton_interp(double x, vector<double>& x_data, vector<double>& y_data) {
int n = x_data.size();
vector<double> div(n); // 系数
div[0] = y_data[0];
for (int i = 1; i < n; i++) {
for (int j = n - 1; j >= i; j--) {
y_data[j] = (y_data[j] - y_data[j - 1]) / (x_data[j] - x_data[j - i]);
}
div[i] = y_data[i];
}
double y = div[n - 1];
for (int i = n - 2; i >= 0; i--) {
y = div[i] + (x - x_data[i]) * y;
}
return y;
}
// 自动选择节点
void select_nodes(int type, vector<double>& x_data, vector<double>& y_data) {
int n = x_data.size();
if (type == 1) { // 线性插值
for (int i = 0; i < n; i++) {
x_data[i] = 1.0 * i / (n - 1);
y_data[i] = sin(2 * M_PI * x_data[i]);
}
} else if (type == 2) { // 抛物线插值
for (int i = 0; i < n; i++) {
x_data[i] = 2.0 * i / (n - 1) - 1;
y_data[i] = 1 / (1 + 25 * x_data[i] * x_data[i]);
}
} else if (type == 3) { // 牛顿插值
for (int i = 0; i < n; i++) {
x_data[i] = -1.0 + 2.0 * i / (n - 1);
y_data[i] = sqrt(115 + x_data[i] * x_data[i]);
}
}
}
// 绘制曲线
void plot_curve(vector<double>& x_data, vector<double>& y_data, string title) {
int n = x_data.size();
Engine* ep = engOpen(NULL);
mxArray* x = mxCreateDoubleMatrix(1, n, mxREAL);
mxArray* y = mxCreateDoubleMatrix(1, n, mxREAL);
double* px = mxGetPr(x);
double* py = mxGetPr(y);
for (int i = 0; i < n; i++) {
px[i] = x_data[i];
py[i] = y_data[i];
}
engPutVariable(ep, "x", x);
engPutVariable(ep, "y", y);
engEvalString(ep, "plot(x, y, '-o');");
engEvalString(ep, "grid on;");
engEvalString(ep, ("title('" + title + "');").c_str());
engEvalString(ep, "xlabel('x');");
engEvalString(ep, "ylabel('y');");
system("pause"); // 暂停等待
engClose(ep);
}
int main() {
int type = 1; // 插值类型:1-线性插值,2-抛物线插值,3-牛顿插值
int n = 11; // 节点数
double x0 = sqrt(115); // 待求点
vector<double> x_data(n), y_data(n);
select_nodes(type, x_data, y_data);
double y_lagrange = lagrange_interp(x0, x_data, y_data);
double y_parabolic = parabolic_interp(x0, x_data, y_data);
double y_newton = newton_interp(x0, x_data, y_data);
cout << "拉格朗日插值法:y(" << x0 << ") = " << y_lagrange << endl;
cout << "抛物线插值法:y(" << x0 << ") = " << y_parabolic << endl;
cout << "牛顿插值法:y(" << x0 << ") = " << y_newton << endl;
plot_curve(x_data, y_data, "Interpolation");
return 0;
}
```
在这里,我们使用了 MATLAB engine 来绘制曲线,需要将 MATLAB 安装目录下的 libeng.lib、libmx.lib、libmat.lib 复制到 Visual Studio 的 lib 目录下,并在项目属性中添加这三个库文件。同时,在 C++ 代码中引入 "mat.h" 头文件即可。如果不需要绘制曲线,可以将相关代码删除或注释。
阅读全文