用C++编写最小二乘法的多项式拟合的程序,对下面这条曲线进行拟合,尽量少用头文件和库,曲线上的点为(0.4,1.075)(0.6,1.115)(0.8,1.16)(1.0,1.225)。要求1:求出它的经验公式,并导出新的点,与原来曲线上的点进行对比。 要求2:最小二乘法多项式拟合产生的线性联立方程用列主元素消去法求解。
时间: 2024-02-09 09:12:41 浏览: 120
好的,我会尽力回答你的问题。首先,最小二乘法是一种常见的数据拟合方法,可以用来求出一个函数的参数,使得该函数与一组给定的数据点最为接近。在多项式拟合中,我们可以用一个多项式函数来拟合给定的数据点,使得该函数能够经过这些点。假设我们要用一个n次多项式函数来拟合给定的m个数据点,那么我们可以列出如下的方程组:
![image.png](attachment:image.png)
其中,x_i 和 y_i 分别表示第i个数据点的横坐标和纵坐标,a_0, a_1, ..., a_n 分别表示多项式的系数。该方程组可以用矩阵表示为:
![image-2.png](attachment:image-2.png)
其中,X是一个m×(n+1)的矩阵,其中每一行都表示一个数据点,每一列都表示多项式的一个系数;y是一个m×1的向量,其中每个元素都表示对应数据点的纵坐标;a是一个(n+1)×1的向量,其中每个元素都表示多项式的一个系数。
我们可以用列主元素消去法来求解该方程组,具体步骤如下:
1.将增广矩阵[A|b]化为上三角矩阵[U|c],其中U是一个n×(n+1)的矩阵,c是一个n×1的向量。
2.从最后一行开始,依次解出每个未知数的值。
3.将求得的未知数代入原方程中,得到拟合曲线的经验公式。
4.根据经验公式,求出新的点,并与原来的数据点进行对比。
下面是用C++编写的最小二乘法多项式拟合的程序:
```c++
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
const int MAXN = 10;
const double eps = 1e-10;
int n; // 多项式的次数
double a[MAXN][MAXN], b[MAXN], x[MAXN]; // 系数矩阵、常数向量、解向量
// 列主元素消去法解线性方程组
bool gauss() {
int i, j, k, p;
double maxa, t;
for (k = 0; k < n; ++k) {
maxa = 0.0;
for (i = k; i < n; ++i) {
if (fabs(a[i][k]) > maxa) {
maxa = fabs(a[i][k]);
p = i;
}
}
if (maxa < eps) return false; // 奇异矩阵
if (p != k) {
for (j = k; j <= n; ++j) {
swap(a[k][j], a[p][j]);
}
swap(b[k], b[p]);
}
for (i = k + 1; i < n; ++i) {
t = a[i][k] / a[k][k];
for (j = k + 1; j <= n; ++j) {
a[i][j] -= t * a[k][j];
}
b[i] -= t * b[k];
}
}
for (i = n - 1; i >= 0; --i) {
for (j = i + 1; j < n; ++j) {
b[i] -= a[i][j] * x[j];
}
x[i] = b[i] / a[i][i];
}
return true;
}
// 拟合函数
double f(double x) {
double res = 0.0;
for (int i = 0; i <= n; ++i) {
res += x * pow(x, i);
}
return res;
}
int main() {
double data[MAXN][2] = {{0.4, 1.075}, {0.6, 1.115}, {0.8, 1.16}, {1.0, 1.225}};
n = 2; // 拟合2次多项式
for (int i = 0; i <= n; ++i) {
for (int j = 0; j <= n; ++j) {
a[i][j] = 0.0;
for (int k = 0; k < 4; ++k) {
a[i][j] += pow(data[k][0], i + j);
}
}
b[i] = 0.0;
for (int k = 0; k < 4; ++k) {
b[i] += pow(data[k][0], i) * data[k][1];
}
}
if (gauss()) {
cout << "经验公式为:y = ";
for (int i = n; i >= 0; --i) {
if (i == n) {
cout << x[i] << "x^" << i << " + ";
} else if (i == 0) {
cout << x[i] << endl;
} else {
cout << x[i] << "x^" << i << " + ";
}
}
cout << "拟合结果如下:" << endl;
cout << setw(10) << "x" << setw(10) << "y1" << setw(10) << "y2" << endl;
double x0 = 0.4, xn = 1.0, dx = 0.01;
for (double xi = x0; xi <= xn; xi += dx) {
double yi1 = f(xi);
double yi2 = 0.0;
for (int i = 0; i <= n; ++i) {
yi2 += x[i] * pow(xi, i);
}
cout << setw(10) << xi << setw(10) << yi1 << setw(10) << yi2 << endl;
}
} else {
cout << "无解" << endl;
}
return 0;
}
```
该程序中,我们首先定义了一个n×(n+1)的系数矩阵a和一个n×1的常数向量b,然后根据给定的数据点,计算出这些系数和常数,构建出一个线性方程组。接着,我们调用列主元素消去法求解该方程组,得到多项式的系数。最后,我们根据这些系数,求出拟合曲线的经验公式,并计算出一组新的点,与原来的数据点进行对比。
阅读全文