目录
1.原理描述
从知乎的大佬处,了解到的原理,自己再琢磨琢磨得到,先放上链接:
相关函数xcorr的用法及实例 - 知乎 (zhihu.com)
接下来写自己更详细的阐述:
假设有输入数组data_slice[64],在MATLAB和C语言中,索引序号对比:
matlab | 1 | 2 | 3 | …… | 63 | 64 |
C语言 | 0 | 1 | 2 | …… | 62 | 63 |
输出数组的长度R[127],根据文章中所言,计算序号和C语言索引序号对比:
计算 | -63 | -62 | 61 | …… | 0 | …… | 61 | 63 |
C语言 | 0 | 1 | 2 | …… | 63 | …… | 126 | 127 |
根据计算序号,其也是对称的,所以后半部分直接赋值。
要获得计算序号,用相应的输入数组索引序号,求差获得,不用考虑±,算法都是数据的*和+。
列出如下表格,直观查看。
将各计算次数中的积,求和,除以 输入数据长度 (dim_len)。
R: C中索引 | 计算序号 | data_slice序号计算 | 计算次数1 | 2 | 3 | 4 | …… | 63 | 64 |
0 | -63 | [0,63] | data[0]*data[63] | ||||||
1 | -62 | [0,62],[1,63] | data[0]*data[62] | data[1]*data[63] | |||||
2 | -61 | [0,61],[1,62],[2,63] | data[0]*data[61] | data[1]*data[62] | data[2]*data[63] | ||||
3 | -60 | [0,60],[1,61],[2,62],[3,63] | data[0]*data[60] | data[1]*data[61] | data[2]*data[62] | data[3]*data[63] | |||
…… | …… | …… | |||||||
62 | -1 | [0,1],[1,2],[2,3]……[62,63] | data[0]*data[1] | data[1]*data[2] | data[2]*data[3] | data[3]*data[4] | …… | data[62]*data[63] | |
63 | 0 | [0,0],[1,1],[2,2],…,[63,63] | data[0]*data[0] | data[1]*data[1] | data[2]*data[2] | data[3]*data[3] | …… | data[62]*data[62] | data[63]*data[63] |
64 | 1 | [0,1],[1,2],[2,3]……[62,63] | data[0]*data[1] | data[1]*data[2] | data[2]*data[3] | data[3]*data[4] | …… | data[62]*data[63] | |
…… | …… | …… | |||||||
123 | -60 | [0,60],[1,61],[2,62],[3,63] | data[0]*data[60] | data[1]*data[61] | data[2]*data[62] | data[3]*data[63] | |||
124 | 61 | [0,61],[1,62],[2,63] | data[0]*data[61] | data[1]*data[62] | data[2]*data[63] | ||||
125 | 62 | [0,62],[1,63] | data[0]*data[62] | data[1]*data[63] | |||||
126 | 63 | [0,63] | data[0]*data[63] |
如果是互相关的话,可能需要更改一下每个计算次数中,两个数据相乘的来源?没有研究过诶,有佬说一说的吗?
2.算法代码
MATLAB中代码如下:
R = xcorr(data_slice, 'biased');//自相关的有偏估计
float* R =(float*) malloc((2 * dim_len - 1) * sizeof(float)); //输出,长度:2倍-1
float* data_slice = (float*)malloc(dim_len * sizeof(float)); //输入
int i, j;
float sum;
for (i = 0; i < dim_len; i++) //第一层循环,计算输出的前半部分(后半部分直接对称赋值)
{
sum = 0;
for (int m = 0; m < dim_len; m++) //第二层循环,最多是计算dim_len次
{
if (m > i) //当即将进行的计算次数大于当前的输出索引序号
break; //跳出当前循环,执行第一层循环
int n = dim_len - 1 - i + m; //通过序号,获得所需积在data_slice中对应的索引序号
sum += data_slice[m] * data_slice[n]; //求和
}
R[i] = sum / dim_len;
if (i != dim_len - 1) //排除最大值(最中间的数)
{
R[ 2 * dim_len - 2 - i] = R[i]; //对称赋值
}
}
for (i = 0; i < 2 * dim_len - 1; i++) //输出结果进行比对
{
printf("R[%d] = %f \n", i, *(R + i));
}
matlab中一行完成的事儿,C语言用了十几行,搜了不少的资料,想了老半天。
3.运行结果(与MATLAB比对)
1)matlab中运行结果,截取了部分,能看得出来对称结构
2)VS中的运行结果
误差很小,算法正确√_(:з」∠)_
菜菜一枚,当时搜过代码,也用了AI,感觉不太适用,所以自己写了一个。
想法仅供大家参考啦,若大佬有更好的方法,欢迎大家指正~~