废话:
上信号与系统后,做实验用Matlab做的卷积,一个函数搞定,但是写实验报告时需要用C语言实现,额,虽说原理不难,实现起来浪费了我好久时间
Y(n)=x(n)h(n)=∑x(i)h(n-i)
先用Matlab演示卷积,后面以这个为例。
a=[1,2,3,4]
b=[1,2,3]
conv(a,b)
ans =
1 4 10 16 17 12
这个一般有两种方法实现
1、第一种是交叉相乘相加法(对于1维的卷积,注意一定要将其中一个倒叙或者翻转180度)
对于同一时间接触到的面积进行相乘,再相加即是这个时刻的值
例子
代码实现
#include
#include
int min(int x, int y) {
return x < y ? x : y;
}
int max(int x, int y) {
return x > y ? x : y;
}
void convolution(int* input1, int* input2, int* output, int mm, int nn)
{
//存储地址
int* xx = (int*)malloc(sizeof(int) * (mm + nn - 1));
//开始卷积
for (int i = 0; i < mm + nn - 1; i++)
{
xx[i] = 0;
//以位数最少的卷积作为卷积次数
for (int j = 0; j < min(mm,nn) ; j++) {
//第一个卷积比第二个卷数积少执行
if (mm <= nn) {
if (i - j >= 0 && i - j < max(mm, nn)) {
printf("%d ", input1[j]);
printf("%d ", input2[i-j]);
xx[i] += input1[j] * input2[i - j];
}
}
//第一个卷积比第二个卷积数多执行
else {
if (i - j >= 0 && i - j < max(mm, nn)) {
printf("%d ", input1[i-j]);
printf("%d ", input2[j]);
xx[i] += input2[j] * input1[i - j];
}
}
printf("\n");
}
}
printf("\n");
for (int i = 0; i < mm+nn-1; i++) {
output[i] = xx[i];
}
delete[] xx;
}
int main() {
int mm, nn;
printf("请输入第一个卷积数目\n");
scanf_s("%d", &mm);
//malloc分配空间
int* input1 = (int*)malloc(sizeof(int) * mm);
printf("请输入第一个卷积数值\n");
for (int i = 0; i < mm; i++) {
scanf_s("%d", &input1[i]);
}
printf("请输入第二个卷积数目\n");
scanf_s("%d", &nn);
int* input2 = (int*)malloc(sizeof(int) * nn);
printf("请输入第二个卷积数值\n");
for (int j = 0; j < nn; j++) {
scanf_s("%d", &input2[j]);
}
//卷积最大空间
int* output = (int*)malloc(sizeof(int) * (mm+nn-1));
convolution(input1, input2, output, mm, nn);
printf("卷积结果\n");
for (int i = 0; i < mm + nn - 1; i++)
{
printf("%d ", output[i]);
}
printf("\n");
return 0;
}
二、第二种方法是时延法(第二种方法相对来说比较简单,转到z域后,卷积变为多项式相乘,不需要对序列进行移动或处理,仅将结果延时相应位数,然后对应相加、提取系数即可。)
已知y[0] = i, y[1] = j, y[2]=k
下面通过演示求x[n] * y[n]的过程,揭示卷积的物理意义。
第一步,x[n]乘以y[0]并平移到位置0
第二步,x[n]乘以y[1]并平移到位置1
第三步,x[n]乘以y[2]并平移到位置2:
最后,把上面三个图叠加,就得到了x[n] * y[n]:
简单吧?无非是平移(没有反褶!)、叠加。
实例
代码实现
#include
#include
void convolution2(int* input1, int* input2, int* output, int mm, int nn)
{
//存储地址
int* xx = (int*)malloc(sizeof(int) * (mm + nn - 1));
for (int i = 0; i < mm + nn - 1; i++) {
xx[i] = 0;
}
//开始卷积
//利用时延效果,记录所有乘积后,时间位置一样的相加
for (int i = 0; i < mm; i++) {
for (int j = 0; j < nn; j++) {
xx[i + j] += input1[i] * input2[j];
}
}
for (int i = 0; i < mm + nn - 1; i++) {
output[i] = xx[i];
}
delete[] xx;
}
int main() {
int mm, nn;
printf("请输入第一个卷积数目\n");
scanf_s("%d", &mm);
//malloc分配空间
int* input1 = (int*)malloc(sizeof(int) * mm);
printf("请输入第一个卷积数值\n");
for (int i = 0; i < mm; i++) {
scanf_s("%d", &input1[i]);
}
printf("请输入第二个卷积数目\n");
scanf_s("%d", &nn);
int* input2 = (int*)malloc(sizeof(int) * nn);
printf("请输入第二个卷积数值\n");
for (int j = 0; j < nn; j++) {
scanf_s("%d", &input2[j]);
}
//卷积最大空间
int* output = (int*)malloc(sizeof(int) * (mm + nn - 1));
convolution2(input1, input2, output, mm, nn);
printf("卷积结果\n");
for (int i = 0; i < mm + nn - 1; i++)
{
printf("%d ", output[i]);
}
printf("\n");
return 0;
}