離散哈特萊變換(DHT)用C語言實現

離散哈特萊變換(DHT)

摘 要

離散哈特萊變換(DHT)是一種與傅里葉變換相關的轉換。類似於離散傅里葉變換。與傅里葉變換在信號處理及其他相關領域有相似的應用。
本設計介紹了DHT的定義以及使用C語言實現其算法。

關鍵字:傅里葉變換 哈特萊變換

二、設計平臺

Linux平臺、GCC編譯器、VIM、windows、Visual Studio 2017

三、設計原理

DHT的定義
設x(n),n=0,1,…,N−1x(n),n=0,1,…,N−1,爲一實序列,其DHT定義爲:

avatar

式中cas(a)=cos(a)+sin(a)cas(a)=cos(a)+sin(a)逆變換(IDHT)爲:

avatar

DHT的正交證明:

avatar

DHT和DFT關係
用X(k)表示實序列x(n)的,用XH(k)表示x(n)的DHT,分別用XHe(k), XHo(k)表示XH(k)的偶對稱分量與奇對稱分量,即:

avatar

其中:

avatar

DHT的優點

DHT爲實值,避免了複數運算

DHT正反變換形式基本一致

DHT與DFT的轉換容易實現

DHT的性質

DHT的性質與DFT的性質類似,但由於DHT是實序列間的變換,有些性質有具體的表達形式。這裏只給出結論。
設x(n)、y(n)的DHT分別爲Xh(k)、Yh(k)。用符號x(n)↔Xh(k)表示Xh(k)=DHT(x(n))。

1.線性性
avatar

2.逆序列x(N-n)的DHT
avatar


avatar

當k=0時,可得Xh(N)=Xh(0)。

3.循環位移的性質
avatar

四、實現代碼

【C語言】

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

const int N = 1024;
const float PI = 3.1416;

inline void swap(float &a, float &b)
{
	float t;
	t = a;
	a = b;
	b = t;
}

void bitrp(float xreal[], float ximag[], int n)
{
	// 位反轉置換 Bit-reversal Permutation
	int i, j, a, b, p;

	for (i = 1, p = 0; i < n; i *= 2)
	{
		p++;
	}
	for (i = 0; i < n; i++)
	{
		a = i;
		b = 0;
		for (j = 0; j < p; j++)
		{
			b = (b << 1) + (a & 1);    // b = b * 2 + a % 2;
			a >>= 1;        // a = a / 2;
		}
		if (b > i)
		{
			swap(xreal[i], xreal[b]);
			swap(ximag[i], ximag[b]);
		}
	}
}

void FFT(float xreal[], float ximag[], int n)
{
	// 快速傅立葉變換,將複數 x 變換後仍保存在 x 中,xreal, ximag 分		//	別是 x 的實部和虛部
	float wreal[N / 2], wimag[N / 2], treal, timag, ureal, uimag, arg;
	int m, k, j, t, index1, index2;

	bitrp(xreal, ximag, n);

	// 計算 1 的前 n / 2 個 n 次方根的共軛複數 W'j = wreal [j] + i * 		wimag [j] , j = 0, 1, ... , n / 2 - 1
	arg = -2 * PI / n;
	treal = cos(arg);
	timag = sin(arg);
	wreal[0] = 1.0;
	wimag[0] = 0.0;
	for (j = 1; j < n / 2; j++)
	{
		wreal[j] = wreal[j - 1] * treal - wimag[j - 1] * timag;
		wimag[j] = wreal[j - 1] * timag + wimag[j - 1] * treal;
	}

	for (m = 2; m <= n; m *= 2)
	{
		for (k = 0; k < n; k += m)
		{
			for (j = 0; j < m / 2; j++)
			{
				index1 = k + j;
				index2 = index1 + m / 2;
				t = n * j / m;    // 旋轉因子 w 的實部在 wreal [] 中					//的下標爲 t
				treal = wreal[t] * xreal[index2] - wimag[t] * 						ximag[index2];
				timag = wreal[t] * ximag[index2] + wimag[t] * 						xreal[index2];
				ureal = xreal[index1];
				uimag = ximag[index1];
				xreal[index1] = ureal + treal;
				ximag[index1] = uimag + timag;
				xreal[index2] = ureal - treal;
				ximag[index2] = uimag - timag;
			}
		}
	}
}



void FFT_test()
{
	float xreal[N] = {}, ximag[N] = {};

	int n = 8;
	int i = 0;
	printf("請輸入數據,格式(實部 虛部) : \n");
	for (i = 0; i < 8; i++)
	{
		scanf("%f%f",xreal+i,ximag+i);
	}

	n = i;    // 要求 n 爲 2 的整數冪
	while (i > 1)
	{
		if (i % 2)
		{
			printf("%d is not a power of 2! ", n);
		}
		i /= 2;
	}

	FFT(xreal, ximag, n);
	printf("=====================================\n");
	printf("FFT:    i	      實部       虛部 \n");
	for (i = 0; i < n; i++)
	{
		printf("     %4d       %8.4f    %8.4f ", i+1, xreal[i], 			ximag[i]);
		printf("\n");
	}
	printf("===================================== \n");

	
	printf("DHT:    i	    結果 \n");
	for (i = 0; i < n; i++)
	{
		printf("     %4d        %8.4f ", i+1, xreal[i]-ximag[i]);
		printf("\n");
	}
	printf("=====================================\n ");
}

int main()
{
	FFT_test();
	system("pause");
	return 0;
}

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章