c语言实现多项式曲线拟合(最小二乘法),与matlab效果一致

前言

最近在弄数字信号处理的内容,需要用到曲线拟合来进行滤波降噪,以下通过c语言来实现算法的内容。

一、代码实现

#define RANK_  	3  		多项式次数
/*
*********************************************************************************************************
*   函 数 名: polyfit
*   功能说明: 多项式曲线拟合(与matlab效果一致)
*   形    参: d_X	输入的数据的x值
			  d_Y	输入的数据的y值
			  d_N	输入的数据的个数
			  rank  多项式的次数
			  coeff 输出的系数
*   返 回 值: 无
*********************************************************************************************************
*/
//原理:At * A * C = At * Y	,其中 At 为 A 转置矩阵,C 为系数矩阵
void polyfit(double *d_X, double *d_Y, int d_N, int rank, double *coeff)
{
	if(RANK_ != rank)	//判断次数是否合法
		return;

	int i,j,k;	
	double aT_A[RANK_ + 1][RANK_ + 1] = {0};
	double aT_Y[RANK_ + 1] = {0};
	
	
	for(i = 0; i < rank + 1; i++)	//行
	{
		for(j = 0; j < rank + 1; j++)	//列
		{
			for(k = 0; k < d_N; k++)	
			{
				aT_A[i][j] +=  pow(d_X[k], i+j);		//At * A 线性矩阵
			}
		}
	}
	
	for(i = 0; i < rank + 1; i++)
	{
		for(k = 0; k < d_N; k++)
		{
			aT_Y[i] += pow(d_X[k], i) * d_Y[k];		//At * Y 线性矩阵
		}
	}
	
	//以下为高斯列主元素消去法解线性方程组
	for(k = 0; k < rank + 1 - 1; k++)
	{
		int row = k;
		double mainElement = fabs(aT_A[k][k]);
		double temp = 0.0;
		
		//找主元素
		for(i = k + 1; i < rank + 1 - 1; i++)
		{
			if( fabs(aT_A[i][i]) > mainElement )
			{
				mainElement = fabs(aT_A[i][i]);
				row = i;
			}
		}
		
		//交换两行
		if(row != k)
		{
			for(i = 0; i < rank + 1; i++)
			{
				temp = aT_A[k][i];
				aT_A[k][i] = aT_A[row][i];
				aT_A[row][i] = temp;
			}	
			temp = aT_Y[k];
			aT_Y[k] = aT_Y[row];
			aT_Y[row] = temp;
		}
			
		
		//消元过程
		for(i = k + 1; i < rank + 1; i++)
		{
			for(j = k + 1; j < rank + 1; j++)
			{
				aT_A[i][j] -= aT_A[k][j] * aT_A[i][k] / aT_A[k][k];
			}
			aT_Y[i] -= aT_Y[k] * aT_A[i][k] / aT_A[k][k];
		}
	}	
		
	//回代过程
	for(i = rank + 1 - 1; i >= 0; coeff[i] /= aT_A[i][i], i--)
	{
		for(j = i + 1, coeff[i] = aT_Y[i]; j < rank + 1; j++)
		{
			coeff[i] -= aT_A[i][j] * coeff[j];
		}
	}

	return;	
}

通过直接修改 RANK_ 宏可以实现不同次数的多项式拟合。

二、结果与 matlab 的 polyfit函数作比较

上面代码实现的结果
在这里插入图片描述
matlab 的 结果
在这里插入图片描述
结果完全一致,完成。

C语言中可以使用最小二乘法进行多项式拟合最小二乘法是一种数学优化技术,用于对一组数据进行拟合,以找到最小化误差平方和的多项式系数。 以下是一个简单的多项式拟合函数的示例代码: ```c #include <stdio.h> #include <math.h> #define MAXN 100 double x[MAXN], y[MAXN], e[MAXN]; void polyfit(int n, int m, double *x, double *y, double *e, double *a) { int i, j, k; double t, w, u, v, *p, *q; p = (double*)malloc(sizeof(double) * (m + 1) * (m + 2) / 2); q = (double*)malloc(sizeof(double) * (m + 1)); for (k = 0; k <= m; k++) { for (j = 0; j <= k; j++) { p[k * (k + 1) / 2 + j] = 0.0; for (i = 0; i < n; i++) p[k * (k + 1) / 2 + j] += pow(x[i], k - j) * e[i]; } } for (k = 0; k <= m; k++) { q[k] = 0.0; for (i = 0; i < n; i++) q[k] += pow(x[i], k) * y[i]; } for (k = 0; k <= m; k++) { t = p[k * (k + 1) / 2 + k]; a[k] = q[k] / t; for (j = k + 1; j <= m; j++) { u = p[j * (j + 1) / 2 + k]; v = t / u; for (i = k + 1; i <= j; i++) p[j * (j + 1) / 2 + i] -= u * p[k * (k + 1) / 2 + i]; q[j] -= v * q[k]; } } for (k = m; k >= 0; k--) { for (a[k] /= p[k * (k + 1) / 2 + k], j = k - 1; j >= 0; j--) a[j] -= p[k * (k + 1) / 2 + j] * a[k]; } free(p); free(q); } int main() { int n, m, i; double a[MAXN]; printf("Enter the number of data points: "); scanf("%d", &n); printf("Enter the degree of polynomial: "); scanf("%d", &m); printf("Enter the data points (x, y):\n"); for (i = 0; i < n; i++) scanf("%lf%lf", &x[i], &y[i]); for (i = 0; i < n; i++) e[i] = 1.0; polyfit(n, m, x, y, e, a); printf("The coefficients of polynomial are:\n"); for (i = 0; i <= m; i++) printf("a[%d] = %lf\n", i, a[i]); return 0; } ``` 在这个示例代码中,我们使用了一个 `polyfit` 函数来进行多项式拟合。该函数使用最小二乘法来计算多项式系数,并返回系数数组。 你需要输入数据点的数量和多项式的次数。然后,你需要输入每个数据点的 x 坐标和 y 坐标。最后,该程序将输出多项式的系数。 注意,这个示例代码中只适用于简单的多项式拟合,如果你需要更高级的拟合,你需要使用其他更高级的算法
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值