卷积——C语言实现

废话:
上信号与系统后,做实验用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;
}

运行结果
卷积——C语言实现_第1张图片

你可能感兴趣的:(算法思想,卷积)