文章目录
函数定义
(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)线性校准
以下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;
}