曲线拟合/平滑算法实现及优化[基于C语言]

用CVI编写个小东西时,发现曲线的拟合已经到了1秒多才能完成一次曲线的拟合。

代码如下:

static void curveFitt (double *pdst,const double *psrc,int len)
{
	const double wind_w=0.4;
	double mypower = pow(10,wind_w/2);
	memcpy(pdst,psrc,len*sizeof(double));
	
	//DEBUG("MYPOWER[%f]",mypower);
	for(int i=(int)mypower+1; i<= len-1 ; i++)
	{
		
		int index_start = (int)( ((double)i/mypower)+(double)1.0);
		int index_end = (int)((double)i*mypower)+1;
		index_end = (index_end>=(len-1))?(len-1):index_end;
		*(pdst+i)= mysum(psrc,index_start,index_end)/(index_end-index_start+1);

		//DEBUG("i[%d],START[%d],end[%d]\n\r",i,index_start,index_end);
	}
	
	return ;
}


//主函数调用处:
{
……
//曲线拟合
long time_s = GetTickCount();				
curveFitt(myFFTHdr.p_fftResult_im,myFFTHdr.p_fftResult_re,ifftPoint>>1);
long time_e = GetTickCount();
DEBUG("curve Fitt diffTime:%d\n\r",time_e-time_s);
……
}

实际效果如下(绿线是经过拟合的):

执行时间如下:

 

优化方向:

1.减少计算的点数,代码如下:

typedef struct __curveData__ {
	int len;//点数
	double *pX;//x坐标数组
	double *pY;//Y坐标数组
}curveData;

//曲线平滑//
#define nPointOfCurveFitt 256 //平滑处理时建议的点数(最终并不一定取到)
#define wideOfFitt 0.4

static void curveFitt (curveData *pdst,curveData *psrc)
{
	double wind_w , wind_w2, mypower;
	int index_start,index_end;
	int i,j,i_tmp;
	wind_w = 0.4 ; //平滑窗的大小
	wind_w2 = log10(psrc->len)/nPointOfCurveFitt; //点数窗
	mypower = pow(10,wind_w/2);
	//mypower2 = pow(10,wind_w);
	j=0;
	//DEBUG("wind_w[%f],mypower[%f],\n\rdst_len[%d],src_len[%d]\n\r",wind_w,mypower,pdst->len,psrc->len);
	for(i=(int)mypower+1; i<= psrc->len-1 ;)
	{
		
		index_start = (int)( ((double)i/mypower)+(double)1.0);
		index_end = (int)((double)i*mypower)+1;
		index_end = (index_end>=(psrc->len-1))?(psrc->len-1):index_end;
		*(pdst->pX+j)= *(psrc->pX+(int)(index_end+index_start)/2);
		*(pdst->pY+j)= mysum(psrc->pY,index_start,index_end)/(index_end-index_start+1);
		
		i_tmp = (int)(pow(10,(log10(i)+wind_w2))+0.5);
		//DEBUG("i[%d],j[%d],i_tmp[%d],pdst->x[%f],pdst->y[%f]\n\r",i,j,i_tmp,*(pdst->pX+j),*(pdst->pY+j));
		//Sleep(1000);
		i=(i_tmp>i)?i_tmp:(i+1);
		j++;
		j=(j>=nPointOfCurveFitt)?nPointOfCurveFitt-1:j;
	}
	//DEBUG("%s\n\r",__func__);
	pdst->len = j;
	return ;
}

实际测试:

运行时间:

------

基本上256点都是在ms级,可以接受。【期待:录音采集在100ms采集一次并运算一次】

 

 

 

 

 

  • 2
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
指数平滑法的计算中,关键是α的取值大小,但α的取值又容易受主观影响,因此合理确定α的取值方法十分重要,一般来说,如果数据波动较大,α值应取大一些,可以增加近期数据对预测结果的影响。如果数据波动平稳,α值应取小一些。理论界一般认为有以下方法可供选择:    经验判断法。这种方法主要依赖于时间序列的发展趋势和预测者的经验做出判断。   1、当时间序列呈现较稳定的水平趋势时,应选较小的α值,一般可在0.05~0.20之间取值;   2、当时间序列有波动,但长期趋势变化不大时,可选稍大的α值,常在0.1~0.4之间取值;   3、当时间序列波动很大,长期趋势变化幅度较大,呈现明显且迅速的上升或下降趋势时,宜选择较大的α值,如可在0.6~0.8间选值,以使预测模型灵敏度高些,能迅速跟上数据的变化;   4、当时间序列数据是上升(或下降)的发展趋势类型,α应取较大的值,在0.6~1之间。   试算法。根据具体时间序列情况,参照经验判断法,来大致确定额定的取值范围,然后取几个α值进行试算,比较不同α值下的预测标准误差,选取预测标准误差最小的α。   在实际应用中预测者应结合对预测对象的变化规律做出定性判断且计算预测误差,并要考虑到预测灵敏度和预测精度是相互矛盾的,必须给予二者一定的考虑,采用折中的α值。 下期预测数=本期实际数×平滑系数+本期预测数×(1-平滑系数) 如某种产品销售量的平滑系数为0.4,1996年实际销售量为31万件,预测销售量为33万件。则1997年的预测销售量为: 1997年预测销售量= 31万件×0.4+33万件×(1-0.4)=32.2万件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值