2022-08-25 15:55:52 +08:00
|
|
|
|
/**
|
2022-08-25 16:34:27 +08:00
|
|
|
|
* @brief 多项式拟合,求解拟合系数。 y=a[0]+a[1]*x^1+a[2]*x^2+...+a[n-1]*x^(n-1)
|
2022-08-25 15:55:52 +08:00
|
|
|
|
*
|
2022-08-25 16:34:27 +08:00
|
|
|
|
* @param xn 输入:自变量。
|
|
|
|
|
* @param yn 输入:因变量。
|
|
|
|
|
* @param n 输入:采样点数量。
|
2022-08-25 17:04:38 +08:00
|
|
|
|
* @param order 输入:拟合次数,最大次数为 5。
|
2022-08-25 16:34:27 +08:00
|
|
|
|
* @param an 输出:拟合系数。
|
|
|
|
|
* @return int 输出:成功返回 0,失败返回 -1。
|
2022-08-25 15:55:52 +08:00
|
|
|
|
*/
|
2022-08-25 16:34:27 +08:00
|
|
|
|
int Polyfit(const double* const xn,
|
|
|
|
|
const double* const yn,
|
|
|
|
|
const unsigned int n,
|
|
|
|
|
const unsigned int order,
|
|
|
|
|
double* const an)
|
2022-08-25 15:55:52 +08:00
|
|
|
|
{
|
|
|
|
|
// Declarations...
|
|
|
|
|
// ----------------------------------
|
|
|
|
|
enum {maxOrder = 5};
|
|
|
|
|
|
|
|
|
|
double B[maxOrder+1] = {0.0};
|
|
|
|
|
double P[((maxOrder+1) * 2)+1] = {0.0};
|
|
|
|
|
double A[(maxOrder + 1)*2*(maxOrder + 1)] = {0.0};
|
|
|
|
|
|
|
|
|
|
double x, y, powx;
|
|
|
|
|
|
|
|
|
|
unsigned int ii, jj, kk;
|
|
|
|
|
|
|
|
|
|
// Verify initial conditions....
|
|
|
|
|
// ----------------------------------
|
|
|
|
|
|
2022-08-25 16:34:27 +08:00
|
|
|
|
// This method requires that the n >
|
2022-08-25 15:55:52 +08:00
|
|
|
|
// (order+1)
|
2022-08-25 16:34:27 +08:00
|
|
|
|
if (n <= order)
|
2022-08-25 15:55:52 +08:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
// This method has imposed an arbitrary bound of
|
|
|
|
|
// order <= maxOrder. Increase maxOrder if necessary.
|
|
|
|
|
if (order > maxOrder)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
// Begin Code...
|
|
|
|
|
// ----------------------------------
|
|
|
|
|
|
|
|
|
|
// Identify the column vector
|
2022-08-25 16:34:27 +08:00
|
|
|
|
for (ii = 0; ii < n; ii++)
|
2022-08-25 15:55:52 +08:00
|
|
|
|
{
|
2022-08-25 16:34:27 +08:00
|
|
|
|
x = xn[ii];
|
|
|
|
|
y = yn[ii];
|
2022-08-25 15:55:52 +08:00
|
|
|
|
powx = 1;
|
|
|
|
|
|
|
|
|
|
for (jj = 0; jj < (order + 1); jj++)
|
|
|
|
|
{
|
|
|
|
|
B[jj] = B[jj] + (y * powx);
|
|
|
|
|
powx = powx * x;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize the PowX array
|
2022-08-25 16:34:27 +08:00
|
|
|
|
P[0] = n;
|
2022-08-25 15:55:52 +08:00
|
|
|
|
|
|
|
|
|
// Compute the sum of the Powers of X
|
2022-08-25 16:34:27 +08:00
|
|
|
|
for (ii = 0; ii < n; ii++)
|
2022-08-25 15:55:52 +08:00
|
|
|
|
{
|
2022-08-25 16:34:27 +08:00
|
|
|
|
x = xn[ii];
|
|
|
|
|
powx = xn[ii];
|
2022-08-25 15:55:52 +08:00
|
|
|
|
|
|
|
|
|
for (jj = 1; jj < ((2 * (order + 1)) + 1); jj++)
|
|
|
|
|
{
|
|
|
|
|
P[jj] = P[jj] + powx;
|
|
|
|
|
powx = powx * x;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize the reduction matrix
|
|
|
|
|
//
|
|
|
|
|
for (ii = 0; ii < (order + 1); ii++)
|
|
|
|
|
{
|
|
|
|
|
for (jj = 0; jj < (order + 1); jj++)
|
|
|
|
|
{
|
|
|
|
|
A[(ii * (2 * (order + 1))) + jj] = P[ii+jj];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
A[(ii*(2 * (order + 1))) + (ii + (order + 1))] = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Move the Identity matrix portion of the redux matrix
|
|
|
|
|
// to the left side (find the inverse of the left side
|
|
|
|
|
// of the redux matrix
|
|
|
|
|
for (ii = 0; ii < (order + 1); ii++)
|
|
|
|
|
{
|
|
|
|
|
x = A[(ii * (2 * (order + 1))) + ii];
|
|
|
|
|
if (x != 0.0)
|
|
|
|
|
{
|
|
|
|
|
for (kk = 0; kk < (2 * (order + 1)); kk++)
|
|
|
|
|
{
|
|
|
|
|
A[(ii * (2 * (order + 1))) + kk] =
|
2022-08-25 16:41:01 +08:00
|
|
|
|
A[(ii * (2 * (order + 1))) + kk] / x;
|
2022-08-25 15:55:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (jj = 0; jj < (order + 1); jj++)
|
|
|
|
|
{
|
|
|
|
|
if ((jj - ii) != 0)
|
|
|
|
|
{
|
|
|
|
|
y = A[(jj * (2 * (order + 1))) + ii];
|
|
|
|
|
for (kk = 0; kk < (2 * (order + 1)); kk++)
|
|
|
|
|
{
|
|
|
|
|
A[(jj * (2 * (order + 1))) + kk] =
|
2022-08-25 16:41:01 +08:00
|
|
|
|
A[(jj * (2 * (order + 1))) + kk] -
|
|
|
|
|
y * A[(ii * (2 * (order + 1))) + kk];
|
2022-08-25 15:55:52 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Cannot work with singular matrices
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-25 16:34:27 +08:00
|
|
|
|
// Calculate and Identify the an
|
2022-08-25 15:55:52 +08:00
|
|
|
|
for (ii = 0; ii < (order + 1); ii++)
|
|
|
|
|
{
|
|
|
|
|
for (jj = 0; jj < (order + 1); jj++)
|
|
|
|
|
{
|
|
|
|
|
x = 0;
|
|
|
|
|
for (kk = 0; kk < (order + 1); kk++)
|
|
|
|
|
{
|
|
|
|
|
x = x + (A[(ii * (2 * (order + 1))) + (kk + (order + 1))] *
|
2022-08-25 16:41:01 +08:00
|
|
|
|
B[kk]);
|
2022-08-25 15:55:52 +08:00
|
|
|
|
}
|
2022-08-25 16:34:27 +08:00
|
|
|
|
an[ii] = x;
|
2022-08-25 15:55:52 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Demo */
|
|
|
|
|
static double Xn[] = {0, 0.3000, 0.6000, 0.9000, 1.2000, 1.5000, 1.8000, 2.1000, 2.4000, 2.7000, 3.0000};
|
|
|
|
|
static double Yn[] = {2.0000, 2.3780, 3.9440, 7.3460, 13.2320, 22.2500, 35.0480, 52.2740, 74.5760, 102.6020, 137.0000};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief 求拟合系数及多项式拟合示例。
|
|
|
|
|
*
|
|
|
|
|
* @return int
|
|
|
|
|
*/
|
|
|
|
|
int main(void)
|
|
|
|
|
{
|
|
|
|
|
double out = 0.0;
|
|
|
|
|
unsigned int i;
|
|
|
|
|
double coff[3];
|
|
|
|
|
|
|
|
|
|
polyfit(Xn, Yn, 11, 2, coff);
|
|
|
|
|
|
|
|
|
|
for (i=0; i<3; i++)
|
|
|
|
|
{
|
|
|
|
|
out += coff[i]*pow(Xn[4], i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|