循环性卷积matlab简单实现

1,052 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

该程序能够实现任意两个序列任意点数的循环卷积,这里我用了两种不同的方法,第一种是用的循环位移将某一序列变成n*n的矩阵,然后与另一个序列相乘;第二种方法是通过循环卷积和线性卷积之间的关系来运算的。 其原理我就不细讲了,课本上都有,然后用的方法也是我们做计算题时最常用的方法。

话不多说,看程序:

%计算循环卷积  自己通过矩阵相乘得出的结果
% input  : 需要做循环卷积的两个序列以及点数
% output : 循环卷积的结果 
length_x2 = length(x2);
length_x1 = length(x1);%求序列的长度
x2n = zeros(1,n); x1n = zeros(1,n);%定义好拓展序列
x2n_f = zeros(n,n); %定义x2拓展后循环位移后的矩阵
if(length_x2<n ||length_x1<n )
    x2n = [x2,zeros(1,n-length_x2)];
    x1n = [x1,zeros(1,n-length_x1)];
    x2n_v = [x2n(1), fliplr(x2n)];
    x2n = x2n_v(1,1:n);
%     x1n_v = [x1n(1), fliplr(x1n)];
%     x1n = x1n_v(1,1:n);
end   %将x1和x2进行n点拓展
i=1;
while (i<=n)
    if(i==1)
        x2n_f(i,:) = x2n(1,:);
    else   
        x2n_f(i,:) = [x2n(n),x2n(1,1:n-1)];
    end
    x2n = x2n_f(i,:);
    i=i+1;
end  %构建矩阵
y = x2n_f*x1n';   %相乘即可
end

这里我们模拟实现过程,细细看一看:

定义x1序列和x2序列

image.png

 n取7,和线性结果的长度一样

执行第一部分 执行第一部分

结果:

执行第二部分:

得到x2n的矩阵

是x2n循环移位后的矩阵,我们要用这个矩阵去算循环卷积。

然后就相乘就可以了。 ​

 最后看一下测试按列:

第二种方法: 当循环卷积的点数大于线性卷积的结果的序列长度时,循环卷积的结果就是线性卷积的结果后面补零。

假设x1[n]长度为M,x2[n]长度为N,则线性卷积长度为L=M+N-1。当进行k点循环卷积时,若K>=L,那么循环卷积的结果就是在线性卷积的结果后面补K-L个零。

当循环卷积的点数小于线性卷积的结果的序列长度时,就会出现重叠。首先要明确的是,重叠L-K个数;其次要知道,怎么重叠的,这里举例子可能更清楚些

这里是x1[n]和x2[n],以及二者线性卷积:

计算5点的循环卷积:

计算六点的:

发现如何叠加的了吧,然后我们就可以写代码实现了:

function  y = circonv_1(x1,x2,n)
% 计算n点的循环卷积,由线性卷积与循环卷积的关系计算循环卷积

yn_line = conv(x1,x2);
yn_length = length(yn_line);
y = zeros(1,n);
if( n>yn_length )
    y = [yn_line,zeros(1,n-yn_length)];
else
    for i = 1:n
        if(i<=yn_length - n)
            y(i) = yn_line(n+i);
        end
        y(i) = y(i)+yn_line(i);
    end
end
        
end

看运行结果:

conclusion:第二种运算方式无论从代码运算上,还是从代码的简易程度上都比第一种更好。