目錄
最小二乘法的原理
擬合函數:
式中:s(x)爲擬合函數, 爲擬合係數,爲函數族
平方誤差:
(1)式可簡化爲線性方程組:
式中:爲函數序列在點上的法方程組。
多項式擬合函數S(x)的基函數爲:
基函數之間的內積爲:
實例:
求解結果:
c++程序源代碼:
//高等數值計算——曲線擬合——最小二乘法
//開發人員:chenshuai 開發日期:2019.11.20 郵箱:[email protected]
#include "pch.h"
#include <iostream>
#include <fstream>//文件輸入/輸出流
#include <iomanip> //參數化輸入/輸出
#define n_polynomial 1 //需要擬合的多項式次數
#include <vector>
using namespace std;
vector<double> least_square_method(vector<double>x, vector<double>y, vector<double>a);//聲明最小二乘法函數,x,y爲原始數據,a爲擬合多項式的係數列向量
double phi(double x, int n_cishu); //函數族計算
vector<double> least_square_method(vector<double>x, vector<double>y, vector<double>a)//最小二乘法函數定義
{
int n_data=size(x),n_num = size(a);
vector<vector<double>>phi_phi;
vector<double>phi_f;
phi_f.resize(n_num);
phi_phi.resize(n_num, vector<double>(n_num));
for (int i = 0; i < n_num; i++)
{
for (int j = 0; j < n_num; j++)
{
for (int k = 0; k < n_data; k++)
{
phi_phi[i][j]= phi_phi[i][j]+phi(x[k],i)*phi(x[k], j);
}
}
for (int k = 0; k < n_data; k++)
{
phi_f[i] = phi_f[i] + phi(x[k], i)*y[k];
}
}
a = gaussian_elimination(phi_phi, phi_f);//多項式係數求解採用高斯消去法“參考我以前寫的文章(含代碼)”https://blog.csdn.net/weixin_41788456/article/details/102485139
//平方誤差求解
double delta_2=0;
for (int i = 0; i < n_data; i++)
{
delta_2 = delta_2 +y[i]*y[i];
}
for (int i = 0; i < n_num; i++)
{
delta_2 = delta_2 - a[i] * phi_f[i];
}
//係數矩陣與平方誤差輸出
for (int i = 0; i < n_num; i++)
{
for (int j = 0; j < n_num; j++)
{
cout << fixed << setprecision(2) << setw(12) << phi_phi[i][j];
}
cout << fixed << setprecision(4) << setw(12) << phi_f[i] << endl;
}
cout << fixed << setprecision(4) << setw(12) << delta_2 << endl;
return a;
}
double phi(double x, int n_cishu) //函數族計算
{
double y;
y = pow(x, n_cishu);
return y;
}
int main()
{
vector<double>x_i= { 1.9,2,2.1,2.5,2.7,2.7,3.5,3.5,4,4,4.5,4.6,5,5.2,6,6.3,6.5,7.1,8,8,8.9,9,9.5,10};//原始數據
vector<double>y_i= { 1.4,1.3,1.8,2.5,2.8,2.5,3,2.7,4,3.5,4.2,3.5,5.5,5,5.5,6.4,6,5.3,6.5,7,8.5,8,8.1,8.1 };
vector<double>a(n_polynomial + 1);
int n_data = size(x_i);
a=least_square_method(x_i, y_i, a);//最小二乘法擬合函數調用
cout << "多項式係數解爲:" << endl;
for (int i = 0; i < n_polynomial + 1; i++)
cout << "a[" << i << "]=" << fixed << setprecision(2) << setw(5) << a[i] << endl;
ofstream out("一次函數擬合函數數據.dat");
double x,y, precision=0.01;
for (x = x_i[0]; x <= x_i.back(); x = x + precision)
{
y = 0.0;
for (int i = 0; i < n_polynomial + 1; i++)
{
y = y + a[i] * pow(x, i);
}
out << fixed << setprecision(4) << setw(12) << x << fixed << setprecision(4) << setw(12) << y << endl;
}
out.close();
ofstream out1("原始數據.dat");
for (int i = 0; i < n_data; i++)
{
out1 << fixed << setprecision(4) << setw(12) << x_i[i] << fixed << setprecision(4) << setw(12) << y_i[i] << endl;
}
out1.close();
}