【C语言常用函数】最小二乘法+线性校准+插值算法+二阶差分求导+均值滤波+标准化处理

函数定义

(1)最小二乘法直线拟合

实验:最小二乘法进行线性拟合之C语言代码

/*--------------------------------------------------------------------
内部函数:最小二乘法直线拟合(y=a*x+b)
-----------------------------------------------------------------------
函数功能:计算方程系数a/b
-----------------------------------------------------------------------
输入参数:
			x_signal				x的序列信号
			y_signal				y的序列信号
			num						信号长度。备注:x和y的元素个数必须相等。
			paras					回归系数。其中,paras[0]=a, paras[1]=b。
-----------------------------------------------------------------------*/
void Least_Square_Linear_Fitting(float x_signal[], float y_signal[], const int num, float* paras)
{
	float sum_x = 0.0;
	float sum_y = 0.0;
	float sum_x2 = 0.0;
	float sum_xy = 0.0;
	for (int ii = 0; ii < num; ii++)
	{
		sum_x += x_signal[ii];
		sum_y += y_signal[ii];
		sum_x2 += x_signal[ii] * x_signal[ii];
		sum_xy += x_signal[ii] * y_signal[ii];
	}
	paras[0] = (num * sum_xy - sum_x * sum_y) / (num * sum_x2 - sum_x * sum_x);
	paras[1] = (sum_x2 * sum_y - sum_x * sum_xy) / (num * sum_x2 - sum_x * sum_x);
}

(2)线性校准

以下K值正负同理:

  • 原理:y0 = y - ( k*x + b )。其中:y0表示校准后的信号,y表示原信号,k表示原信号的斜率,b表示原信号的截距,x表示[1,2,3...]序号。
  • 效果:随着x越大,幅值增减越大。
  • 原因:以起始点为平稳线,若斜率k越大,则表面后面的信号越陡峭,故需要校准的值越大。
  • 结论:(1)校准后信号段的斜率k趋近于0;(2)若公式中加入b,则信号段的均值为0(将信号段的坐标变换到原点);若公式中去掉b,则信号段的均值为原信号的起始点(保留原信号段的坐标不变)。
/*--------------------------------------------------------------------
内部函数:线性校准(y=k*x+b)
-----------------------------------------------------------------------
函数功能:在不改变信号形状的情形下,使得变换后信号的斜率 k 趋近于0。
-----------------------------------------------------------------------
输入参数:
			x_signal				x的序列信号:range( 1:1:len(signal) )
			y_signal				y的序列信号
			num						信号长度。备注:x和y的元素个数必须相等。
			paras					回归系数。其中,paras[0]=a, paras[1]=b。
-----------------------------------------------------------------------*/
void Linear_Calibration(float x_signal[], float y_signal[], const int num, float* paras)
{
	Least_Square_Linear_Fitting(x_signal, y_signal, num, paras);
	for (int ii = 0; ii <= num; ii++)
	{
		y_signal[ii] = y_signal[ii] - paras[0] * x_signal[ii];						//信号的斜率趋近于0
		//y_signal[ii] = y_signal[ii] - (paras[0] * x_signal[ii] + paras[1]);		//信号的斜率趋近于0,且映射到x=0。即均值=0.
	}
}

(3)拉格朗日插值算法

插值算法.ppt(详细介绍:原理与图解)
(1)一维插值算法:最近邻插值、线性插值、拉格朗日插值、牛顿插值、三次样条插值
(2)二维插值算法:最近邻插值、双线性插值、三次卷积插值


实验:Lagrange拉格朗日插值法之C语言代码
实验:Newton牛顿插值法之C语言代码

/*--------------------------------------------------------------------
内部函数:拉格朗日插值(Polynomial interpolation)
-----------------------------------------------------------------------
多项式公式:f(x) = a(0) + a(1)*x + a(2)*(x^2) + ... + a(n) * (x^n)
-----------------------------------------------------------------------
输入参数:
			x_signal				x的序列信号
			y_signal				y的序列信号
			num						信号长度。备注:x和y的元素个数必须相等。
			t						指定插值点
-----------------------------------------------------------------------*/
float Lagrange_Interpolation(float x [], float y [], const int num, float t)
{
	float z_value = 0.0; 		//插值点的拟合值
	if (num <= 0) {;}
	else if (num == 1) { z_value = y[0]; }
	else if (num == 2) { z_value = (y[0] * (t - x[1]) - y[1] * (t - x[0])) / (x[0] - x[1]); }
	else if (num >= 3)
	{
		//利用拉格朗日插值公式,计算在t点对应的f(t)。
		for (int ii = 0; ii <= num; ii++)
		{
			float s_base = 1.0;		//s是拉格朗日基函数
			for (int jj = 0; jj <= num; jj++)
				if (jj != ii)			//去掉xi与xj相等的情况,分母为0没意义。
					s_base = s_base * (t - x[jj]) / (x[ii] - x[jj]);		//拉格朗日插值公式
			z_value = z_value + s_base * y[ii];		//(基函数 * y)的累加计算,得到该x想的拉格朗日函数。
		}
	}
	return z_value;
}

(4)二阶差分求导

/*--------------------------------------------------------------------
内部函数:差分
-----------------------------------------------------------------------
函数说明:后一个减前一个
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			diff_signal				差分后的信号
-----------------------------------------------------------------------*/
void Diff(float signal[], int signal_len, float* diff_signal)
{
	for (int ii = 0; ii < signal_len - 1; ii++)
	{
		diff_signal[ii] = signal[ii+1] - signal[ii];
	}
}

/*--------------------------------------------------------------------
内部函数:二阶差分求导
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			_points					导数对应的信号点(可能存在多个)
			max_or_min				极大值/极小值(可能存在多个)
-----------------------------------------------------------------------*/
void Two_Order_Diff(float signal[], int signal_len, float* _points, int* max_or_min)
{
	//一阶差分
	float diff_signal[1000] = {0.0};
	Diff(signal, signal_len, diff_signal);
	for (int ii = 0; ii < (signal_len - 1) - 1; ii++)
	{
		if (diff_signal[ii] >= 0)
			diff_signal[ii] = 1;
		else if (diff_signal[ii] < 0)
			diff_signal[ii] = -1;
	}

	//二阶差分
	float Two_diff_signal[1000] = {0.0};
	Diff(diff_signal, (signal_len - 1), Two_diff_signal);
	int point_num = 0;		//极值点个数
	for (int ii = 0; ii < (signal_len - 1) - 1; ii++)
	{
		if (Two_diff_signal[ii] == -2 || Two_diff_signal[ii] == 2)
		{
			//-2 = -1 - (+1):即先上升后下降(极大值点)
			// 2 = 1 - (-1):即先下降后上升(极小值点)
			max_or_min[point_num] = Two_diff_signal[ii];
			_points[point_num] = ii;
			point_num++;
		}
	}
}

(5)均值滤波

/*--------------------------------------------------------------------
内部函数:均值滤波 
-----------------------------------------------------------------------
函数功能:去除异常波动或噪声影响 
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			filter_size				滤波器窗口大小
			mean_signal				均值滤波后的信号
-----------------------------------------------------------------------*/
void Mean_Filter(float signal[], const int signal_len, const int filter_size, float* mean_signal)
{
	for (int ii = 0; ii < signal_len - filter_size + 1; ii++)
	{
		float part_signal = 0;
		for (int jj = 0; jj < filter_size; jj++)
			part_signal += signal[ii + jj] / filter_size;
		mean_signal[ii] = part_signal;
	}
}

(6)标准化处理

/*--------------------------------------------------------------------
内部函数:标准化处理(Standardization) 
-----------------------------------------------------------------------
函数说明:均值为0,标准差为1的标准正态分布N(0,1) 
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			mean_signal				均值滤波后的信号
-----------------------------------------------------------------------*/
void Standardization(float signal[], const int signal_len, float* standard_signal)
{
	//均值
	float mean_value = 0.0;
	for (int ii = 0; ii < signal_len; ii++)
		mean_value += signal[ii] / signal_len;	
	//标准差
	float stand_value = 0.0;
	for (int jj = 0; jj < signal_len; jj++)
		stand_value += (signal[jj] - mean_value) * (signal[jj] - mean_value);
	stand_value = (float)sqrt(stand_value / signal_len);		//(float)sqrt(double x):double 强转float
	//标准化处理
	for (int kk = 0; kk < signal_len; kk++)	
		standard_signal[kk] = (signal[kk] - mean_value) / stand_value;
}

函数调用

方法一:将所有代码都放到一个文件中

#include <time.h>	
#include<algorithm >
#include<stdio.h>

//1最小二乘法直线拟合
/*--------------------------------------------------------------------
内部函数:最小二乘法直线拟合(y=a*x+b)
-----------------------------------------------------------------------
函数功能:计算方程系数a/b
-----------------------------------------------------------------------
输入参数:
			x_signal				x的序列信号
			y_signal				y的序列信号
			num						信号长度。备注:x和y的元素个数必须相等。
			paras					回归系数。其中,paras[0]=a, paras[1]=b。
-----------------------------------------------------------------------*/
void Least_Square_Linear_Fitting(float x_signal[], float y_signal[], const int num, float* paras)
{
	float sum_x = 0.0;
	float sum_y = 0.0;
	float sum_x2 = 0.0;
	float sum_xy = 0.0;
	for (int ii = 0; ii < num; ii++)
	{
		sum_x += x_signal[ii];
		sum_y += y_signal[ii];
		sum_x2 += x_signal[ii] * x_signal[ii];
		sum_xy += x_signal[ii] * y_signal[ii];
	}
	paras[0] = (num * sum_xy - sum_x * sum_y) / (num * sum_x2 - sum_x * sum_x);
	paras[1] = (sum_x2 * sum_y - sum_x * sum_xy) / (num * sum_x2 - sum_x * sum_x);
}
			
			
//2线性校准
/*--------------------------------------------------------------------
内部函数:线性校准(y=k*x+b)
-----------------------------------------------------------------------
函数功能:在不改变信号形状的情形下,使得变换后信号的斜率 k 趋近于0。
-----------------------------------------------------------------------
输入参数:
			x_signal				x的序列信号:range( 1:1:len(signal) )
			y_signal				y的序列信号
			num						信号长度。备注:x和y的元素个数必须相等。
			paras					回归系数。其中,paras[0]=a, paras[1]=b。
-----------------------------------------------------------------------*/
void Linear_Calibration(float x_signal[], float y_signal[], const int num, float* paras)
{
	Least_Square_Linear_Fitting(x_signal, y_signal, num, paras);
	for (int ii = 0; ii <= num; ii++)
	{
		y_signal[ii] = y_signal[ii] - paras[0] * x_signal[ii];						//信号的斜率趋近于0
		//y_signal[ii] = y_signal[ii] - (paras[0] * x_signal[ii] + paras[1]);		//信号的斜率趋近于0,且映射到x=0。即均值=0.
	}
}
	
	
//3拉格朗日插值算法
/*--------------------------------------------------------------------
内部函数:拉格朗日插值(Polynomial interpolation)
-----------------------------------------------------------------------
多项式公式:f(x) = a(0) + a(1)*x + a(2)*(x^2) + ... + a(n) * (x^n)
-----------------------------------------------------------------------
输入参数:
			x_signal				x的序列信号
			y_signal				y的序列信号
			num						信号长度。备注:x和y的元素个数必须相等。
			t						指定插值点
-----------------------------------------------------------------------*/
float Lagrange_Interpolation(float x [], float y [], const int num, float t)
{
	float z_value = 0.0; 		//插值点的拟合值
	if (num <= 0) {;}
	else if (num == 1) { z_value = y[0]; }
	else if (num == 2) { z_value = (y[0] * (t - x[1]) - y[1] * (t - x[0])) / (x[0] - x[1]); }
	else if (num >= 3)
	{
		//利用拉格朗日插值公式,计算在t点对应的f(t)。
		for (int ii = 0; ii <= num; ii++)
		{
			float s_base = 1.0;		//s是拉格朗日基函数
			for (int jj = 0; jj <= num; jj++)
				if (jj != ii)			//去掉xi与xj相等的情况,分母为0没意义。
					s_base = s_base * (t - x[jj]) / (x[ii] - x[jj]);		//拉格朗日插值公式
			z_value = z_value + s_base * y[ii];		//(基函数 * y)的累加计算,得到该x想的拉格朗日函数。
		}
	}
	return z_value;
}


//4差分算法
/*--------------------------------------------------------------------
内部函数:差分
-----------------------------------------------------------------------
函数说明:后一个减前一个
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			diff_signal				差分后的信号
-----------------------------------------------------------------------*/
void Diff(float signal[], int signal_len, float* diff_signal)
{
	for (int ii = 0; ii < signal_len - 1; ii++)
	{
		diff_signal[ii] = signal[ii+1] - signal[ii];
	}
}


//5二阶差分求导
/*--------------------------------------------------------------------
内部函数:二阶差分求导
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			_points					导数对应的信号点(可能存在多个)
			max_or_min				极大值/极小值(可能存在多个)
-----------------------------------------------------------------------*/
void Two_Order_Diff(float signal[], int signal_len, float* _points, int* max_or_min)
{
	//一阶差分
	float diff_signal[1000] = {0.0};
	Diff(signal, signal_len, diff_signal);
	for (int ii = 0; ii < (signal_len - 1) - 1; ii++)
	{
		if (diff_signal[ii] >= 0)
			diff_signal[ii] = 1;
		else if (diff_signal[ii] < 0)
			diff_signal[ii] = -1;
	}

	//二阶差分
	float Two_diff_signal[1000] = {0.0};
	Diff(diff_signal, (signal_len - 1), Two_diff_signal);
	int point_num = 0;		//极值点个数
	for (int ii = 0; ii < (signal_len - 1) - 1; ii++)
	{
		if (Two_diff_signal[ii] == -2 || Two_diff_signal[ii] == 2)
		{
			//-2 = -1 - (+1):即先上升后下降(极大值点)
			// 2 = 1 - (-1):即先下降后上升(极小值点)
			max_or_min[point_num] = Two_diff_signal[ii];
			_points[point_num] = ii;
			point_num++;
		}
	}
}


//6均值滤波
/*--------------------------------------------------------------------
内部函数:均值滤波 
-----------------------------------------------------------------------
函数功能:去除异常波动或噪声影响 
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			filter_size				滤波器窗口大小
			mean_signal				均值滤波后的信号
-----------------------------------------------------------------------*/
void Mean_Filter(float signal[], const int signal_len, const int filter_size, float* mean_signal)
{
	for (int ii = 0; ii < signal_len - filter_size + 1; ii++)
	{
		float part_signal = 0;
		for (int jj = 0; jj < filter_size; jj++)
			part_signal += signal[ii + jj] / filter_size;
		mean_signal[ii] = part_signal;
	}
}


//7标准化处理
/*--------------------------------------------------------------------
内部函数:标准化处理(Standardization) 
-----------------------------------------------------------------------
函数说明:均值为0,标准差为1的标准正态分布N(0,1) 
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			mean_signal				均值滤波后的信号
-----------------------------------------------------------------------*/
void Standardization(float signal[], const int signal_len, float* standard_signal)
{
	//均值
	float mean_value = 0.0;
	for (int ii = 0; ii < signal_len; ii++)
		mean_value += signal[ii] / signal_len;	
	//标准差
	float stand_value = 0.0;
	for (int jj = 0; jj < signal_len; jj++)
		stand_value += (signal[jj] - mean_value) * (signal[jj] - mean_value);
	stand_value = (float)sqrt(stand_value / signal_len);		//(float)sqrt(double x):double 强转float
	//标准化处理
	for (int kk = 0; kk < signal_len; kk++)	
		standard_signal[kk] = (signal[kk] - mean_value) / stand_value;
}



int main(int argc, char* argv[])
{			
	//1、最小二乘法直线拟合
	int size = 100;
	float x_rand[100] = {0.0};
	float y_rand[100] = {0.0};
	float paras[] = {0.0, 0.0};
	for (int ii = 0; ii < size; ii++)
	{
		srand((unsigned)time(0));			//使用当前时刻做种子
		x_rand[ii] = ii + 1;
		y_rand[ii] = rand()%100 + 1;		//生成1~100随机数
	}
	Least_Square_Linear_Fitting(x_rand, y_rand, size, paras);
	printf("\ny = %f + %f*x", paras[0], paras[1]);
	
	//2、线性校准
	printf("\n\n原始信号:");
	for (int ii = 0; ii < size ; ii++)
		printf("%16f", y_rand[ii]);
	Linear_Calibration(x_rand, y_rand, size, paras);
	printf("\n\n校准后信号:");
	for (int ii = 0; ii < size ; ii++)
		printf("%16f", y_rand[ii]);

	//3、拉格朗日插值算法 
	float x[] = {11, 12, 13};
	float y[] = {0.190809, 0.207912, 0.224951};
	int num = 3;
	float t = 11.5;
	float t_y = Lagrange_Interpolation(x, y, num, t);
	printf("\nx = %f;	f(x) = %f", t, t_y);
	//计算结果:x = 11.500000;	f(x) = 0.199368 
	
	//4、二阶差分求导
	float signal_diff[100] = {0.0};
	for (int ii = 0; ii < size; ii++)
	{
		//srand((unsigned)time(0));				//使用当前时刻做种子
		signal_diff[ii] = rand()%100 + 1;		//生成1~100随机数
	}
	int signal_diff_len = 100;
	float _points[100] = {0.0};
	int max_or_min[100] = {0.0};
	Two_Order_Diff( signal_diff, signal_diff_len, _points, max_or_min );
	int num_point = 0;
	for (int ii = 0; ii < sizeof(max_or_min) / sizeof(int); ii++)
	{
		if (max_or_min[ii] != 0.0)
			num_point++;
	}
	printf("\n共有%d个导数", num_point);

	//5、均值滤波
	float signal_mean[100] = {0.0};
	for (int ii = 0; ii < size; ii++)
	{
		//srand((unsigned)time(0));				//使用当前时刻做种子
		signal_mean[ii] = rand()%100 + 1;		//生成1~100随机数
	}
	int signal_mean_len = 100;
	int filter_size = 10;
	float mean_signal[100] = {0.0};
	Mean_Filter(signal_mean, signal_mean_len, filter_size, mean_signal);
	printf("\n\n原始信号:");
	for (int ii = 0; ii < sizeof(signal_mean) / sizeof(int); ii++)
		printf("%16f", signal_mean[ii]);
	printf("\n\n均值信号:");
	for (int ii = 0; ii < sizeof(mean_signal) / sizeof(int); ii++)
		printf("%16f", mean_signal[ii]);

	//6、标准化处理
	float signal_standard[100] = {0.0};
	for (int ii = 0; ii < size; ii++)
	{
		//srand((unsigned)time(0));					//使用当前时刻做种子
		signal_standard[ii] = rand()%100 + 1;		//生成1~100随机数
	}
	int signal_standard_len = 100;
	float standard_signal[100] = {0.0};
	Standardization(signal_standard, signal_standard_len, standard_signal);
	printf("\n\n标准化信号:");
	for (int ii = 0; ii < sizeof(standard_signal) / sizeof(int); ii++)
		printf("%16f", standard_signal[ii]);

	return 0;
}

方法二:(.exe)调用C/C++生成的(.lib)

环境配置教程

(11)头文件(General_Function.h)

#pragma once

void Least_Square_Linear_Fitting(float x_signal[], float y_signal[], const int num, float* paras);
float Lagrange_Interpolation(float x [], float y [], const int num, float t);
void Diff(float signal[], int signal_len, float* diff_signal);
void Two_Order_Diff(float signal[], int signal_len, float* _points, int* max_or_min);
void Mean_Filter(float signal[], const int signal_len, const int filter_size, float* mean_signal);
void Standardization(float signal[], const int signal_len, float* standard_signal);
void Linear_Calibration(float x_signal[], float y_signal[], const int num, float* paras);

(22)源文件(General_Function.c)

#include "General_Function.h"
#include <math.h>


//0条件判断
/*--------------------------------------------------------------------
内部函数:条件判断
-----------------------------------------------------------------------
输入参数:
			data 				需要判断的数组
			condition			判断条件。结构体数组
-----------------------------------------------------------------------
struct __condition
{
	float upper_value;
	float lower_value;
};
void condition_judge(float* data, __condition condition[10])
{
	for (int ii = 0; ii < 10; ii++)
	{
		if (condition[ii].lower_value < data[ii] && data[ii] < condition[ii].upper_value)
			data[ii] = 1;
		else
			data[ii] = 0;
	}
}


//1最小二乘法直线拟合
/*--------------------------------------------------------------------
内部函数:最小二乘法直线拟合(y=a*x+b)
-----------------------------------------------------------------------
函数功能:计算方程系数a/b
-----------------------------------------------------------------------
输入参数:
			x_signal			x的序列信号
			y_signal			y的序列信号
			num					信号长度。备注:x和y的元素个数必须相等。
			paras				回归系数。其中,paras[0]=a, paras[1]=b。
-----------------------------------------------------------------------*/
void Least_Square_Linear_Fitting(float x_signal[], float y_signal[], const int num, float* paras)
{
	float sum_x = 0.0;
	float sum_y = 0.0;
	float sum_x2 = 0.0;
	float sum_xy = 0.0;
	for (int ii = 0; ii < num; ii++)
	{
		sum_x += x_signal[ii];
		sum_y += y_signal[ii];
		sum_x2 += x_signal[ii] * x_signal[ii];
		sum_xy += x_signal[ii] * y_signal[ii];
	}
	paras[0] = (num * sum_xy - sum_x * sum_y) / (num * sum_x2 - sum_x * sum_x);
	paras[1] = (sum_x2 * sum_y - sum_x * sum_xy) / (num * sum_x2 - sum_x * sum_x);
}
			

//2线性校准
/*--------------------------------------------------------------------
内部函数:线性校准(y=k*x+b)
-----------------------------------------------------------------------
函数功能:在不改变信号形状的情形下,使得变换后信号的斜率 k 趋近于0。
-----------------------------------------------------------------------
输入参数:
			x_signal				x的序列信号:range( 1:1:len(signal) )
			y_signal				y的序列信号
			num						信号长度。备注:x和y的元素个数必须相等。
			paras					回归系数。其中,paras[0]=a, paras[1]=b。
-----------------------------------------------------------------------*/
void Linear_Calibration(float x_signal[], float y_signal[], const int num, float* paras)
{
	Least_Square_Linear_Fitting(x_signal, y_signal, num, paras);
	for (int ii = 0; ii <= num; ii++)
	{
		y_signal[ii] = y_signal[ii] - paras[0] * x_signal[ii];						//信号的斜率趋近于0
		//y_signal[ii] = y_signal[ii] - (paras[0] * x_signal[ii] + paras[1]);		//信号的斜率趋近于0,且映射到x=0。即均值=0.
	}
}
	

//3拉格朗日插值算法
/*--------------------------------------------------------------------
内部函数:拉格朗日插值(Polynomial interpolation)
-----------------------------------------------------------------------
多项式公式:f(x) = a(0) + a(1)*x + a(2)*(x^2) + ... + a(n) * (x^n)
-----------------------------------------------------------------------
输入参数:
			x_signal			x的序列信号
			y_signal			y的序列信号
			num					信号长度。备注:x和y的元素个数必须相等。
			t					指定插值点
-----------------------------------------------------------------------*/
float Lagrange_Interpolation(float x [], float y [], const int num, float t)
{
	float z_value = 0.0; 		//插值点的拟合值
	if (num <= 0) {;}
	else if (num == 1) { z_value = y[0]; }
	else if (num == 2) { z_value = (y[0] * (t - x[1]) - y[1] * (t - x[0])) / (x[0] - x[1]); }
	else if (num >= 3)
	{
		//利用拉格朗日插值公式,计算在t点对应的f(t)。
		for (int ii = 0; ii <= num; ii++)
		{
			float s_base = 1.0;		//s是拉格朗日基函数
			for (int jj = 0; jj <= num; jj++)
				if (jj != ii)			//去掉xi与xj相等的情况,分母为0没意义。
					s_base = s_base * (t - x[jj]) / (x[ii] - x[jj]);		//拉格朗日插值公式
			z_value = z_value + s_base * y[ii];		//(基函数 * y)的累加计算,得到该x想的拉格朗日函数。
		}
	}
	return z_value;
}


//4差分算法
/*--------------------------------------------------------------------
内部函数:差分
-----------------------------------------------------------------------
函数说明:后一个减前一个
-----------------------------------------------------------------------
输入参数:
			signal				序列信号
			signal_len			信号长度
			diff_signal			差分后的信号
-----------------------------------------------------------------------*/
void Diff(float signal[], int signal_len, float* diff_signal)
{
	for (int ii = 0; ii < signal_len - 1; ii++)
	{
		diff_signal[ii] = signal[ii+1] - signal[ii];
	}
}


//5二阶差分求导
/*--------------------------------------------------------------------
内部函数:二阶差分求导
-----------------------------------------------------------------------
输入参数:
			signal				序列信号
			signal_len			信号长度
			_points				导数对应的信号点(可能存在多个)
			max_or_min			极大值/极小值(可能存在多个)
-----------------------------------------------------------------------*/
void Two_Order_Diff(float signal[], int signal_len, float* _points, int* max_or_min)
{
	//一阶差分
	float diff_signal[1000] = {0.0};
	Diff(signal, signal_len, diff_signal);
	for (int ii = 0; ii < (signal_len - 1) - 1; ii++)
	{
		if (diff_signal[ii] >= 0)
			diff_signal[ii] = 1;
		else if (diff_signal[ii] < 0)
			diff_signal[ii] = -1;
	}

	//二阶差分
	float Two_diff_signal[1000] = {0.0};
	Diff(diff_signal, (signal_len - 1), Two_diff_signal);
	int point_num = 0;		//极值点个数
	for (int ii = 0; ii < (signal_len - 1) - 1; ii++)
	{
		if (Two_diff_signal[ii] == -2 || Two_diff_signal[ii] == 2)
		{
			//-2 = -1 - (+1):即先上升后下降(极大值点)
			// 2 = 1 - (-1):即先下降后上升(极小值点)
			max_or_min[point_num] = Two_diff_signal[ii];
			_points[point_num] = ii;
			point_num++;
		}
	}
}


//6均值滤波
/*--------------------------------------------------------------------
内部函数:均值滤波 
-----------------------------------------------------------------------
函数功能:去除异常波动或噪声影响 
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			filter_size				滤波器窗口大小
			mean_signal				均值滤波后的信号
-----------------------------------------------------------------------*/
void Mean_Filter(float signal[], const int signal_len, const int filter_size, float* mean_signal)
{
	for (int ii = 0; ii < signal_len - filter_size + 1; ii++)
	{
		float part_signal = 0;
		for (int jj = 0; jj < filter_size; jj++)
			part_signal += signal[ii + jj] / filter_size;
		mean_signal[ii] = part_signal;
	}
}


//7标准化处理
/*--------------------------------------------------------------------
内部函数:标准化处理(Standardization) 
-----------------------------------------------------------------------
函数说明:均值为0,标准差为1的标准正态分布N(0,1) 
-----------------------------------------------------------------------
输入参数:
			signal					序列信号
			signal_len				信号长度
			mean_signal				均值滤波后的信号
-----------------------------------------------------------------------*/
void Standardization(float signal[], const int signal_len, float* standard_signal)
{
	//均值
	float mean_value = 0.0;
	for (int ii = 0; ii < signal_len; ii++)
		mean_value += signal[ii] / signal_len;	
	//标准差
	float stand_value = 0.0;
	for (int jj = 0; jj < signal_len; jj++)
		stand_value += (signal[jj] - mean_value) * (signal[jj] - mean_value);
	stand_value = (float)sqrt(stand_value / signal_len);		//(float)sqrt(double x):double 强转float
	//标准化处理
	for (int kk = 0; kk < signal_len; kk++)	
		standard_signal[kk] = (signal[kk] - mean_value) / stand_value;
}

(33)新建项目(Test.exe)

#include "General_Function.c"
#include <time.h>	
#include <algorithm >
#include <stdio.h>
int main(int argc, char* argv[])
{			
	//0、条件判断
	float data[10] = {0.0};
	struct __condition condition[10];
	for (int ii = 0; ii < 10; ii++)
	{
		//srand((unsigned)time(0));			//使用当前时刻做种子
		data[ii] = rand()%20 + 5;			//生成5~20随机数
	}
	for (int ii = 0; ii < 10; ii++)
	{
		condition[ii].lower_value = 1;
		condition[ii].upper_value = 10;
	}
	condition_judge(data, condition);
	for (int ii = 0; ii < 10; ii++)
		printf("%16f", data[ii]);


	//1、最小二乘法直线拟合
	int size = 100;
	float x_rand[100] = {0.0};
	float y_rand[100] = {0.0};
	float paras[] = {0.0, 0.0};
	for (int ii = 0; ii < size; ii++)
	{
		//srand((unsigned)time(0));			//使用当前时刻做种子
		x_rand[ii] = ii + 1;
		y_rand[ii] = rand()%100 + 1;		//生成1~100随机数
	}
	Least_Square_Linear_Fitting(x_rand, y_rand, size, paras);
	printf("\ny = %f + %f*x", paras[0], paras[1]);


	//2、线性校准
	printf("\n\n原始信号:");
	for (int ii = 0; ii < size ; ii++)
		printf("%16f", y_rand[ii]);
	Linear_Calibration(x_rand, y_rand, size, paras);
	printf("\n\n校准后信号:");
	for (int ii = 0; ii < size ; ii++)
		printf("%16f", y_rand[ii]);
		

	//2、拉格朗日插值算法 
	float x[] = {11, 12, 13};
	float y[] = {0.190809, 0.207912, 0.224951};
	int num = 3;
	float t = 11.5;
	float t_y = Lagrange_Interpolation(x, y, num, t);
	printf("\nx = %f;	f(x) = %f", t, t_y);
	//计算结果:x = 11.500000;	f(x) = 0.199368 
	
	//3、二阶差分求导
	float signal_diff[100] = {0.0};
	for (int ii = 0; ii < size; ii++)
	{
		//srand((unsigned)time(0));				//使用当前时刻做种子
		signal_diff[ii] = rand()%100 + 1;		//生成1~100随机数
	}
	int signal_diff_len = 100;
	float _points[100] = {0.0};
	int max_or_min[100] = {0.0};
	Two_Order_Diff( signal_diff, signal_diff_len, _points, max_or_min );
	int num_point = 0;
	for (int ii = 0; ii < sizeof(max_or_min) / sizeof(int); ii++)
	{
		if (max_or_min[ii] != 0.0)
			num_point++;
	}
	printf("\n共有%d个导数", num_point);

	//4、均值滤波
	float signal_mean[100] = {0.0};
	for (int ii = 0; ii < size; ii++)
	{
		//srand((unsigned)time(0));				//使用当前时刻做种子
		signal_mean[ii] = rand()%100 + 1;		//生成1~100随机数
	}
	int signal_mean_len = 100;
	int filter_size = 10;
	float mean_signal[100] = {0.0};
	Mean_Filter(signal_mean, signal_mean_len, filter_size, mean_signal);
	printf("\n\n原始信号:");
	for (int ii = 0; ii < sizeof(signal_mean) / sizeof(int); ii++)
		printf("%16f", signal_mean[ii]);
	printf("\n\n均值信号:");
	for (int ii = 0; ii < sizeof(mean_signal) / sizeof(int); ii++)
		printf("%16f", mean_signal[ii]);

	//5、标准化处理
	float signal_standard[100] = {0.0};
	for (int ii = 0; ii < size; ii++)
	{
		//srand((unsigned)time(0));					//使用当前时刻做种子
		signal_standard[ii] = rand()%100 + 1;		//生成1~100随机数
	}
	int signal_standard_len = 100;
	float standard_signal[100] = {0.0};
	Standardization(signal_standard, signal_standard_len, standard_signal);
	printf("\n\n标准化信号:");
	for (int ii = 0; ii < sizeof(standard_signal) / sizeof(int); ii++)
		printf("%16f", standard_signal[ii]);

	return 0;
}

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖墩会武术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值