实数FFT可以利用变换的对称性或快速哈特莱变换来减少乘法运算,理论上乘法运算量可以减少约一半,然而在目前的计算机上实际运算时间确更长。
1、测试代码
(1)利用FFT直接计算实数FFT变换
void FFT1(Complex Xn[], int R2N, double data[], int N)
{
//赋值
for (int i = 0; i < N; i++)
{
Xn[i] = data[i];
}
//补零
memset(Xn + N, 0, (R2N - N) * sizeof(Complex));
FFT(Xn, R2N);
}
(2)利用哈特莱变换换算FFT
void FFT2(Complex Xn[], int R2N, double data[], int N)
{
double *Yn = reinterpret_cast<double*>(Xn);
int N2 = R2N >> 1;
//赋值
memcpy(Yn, data, N * sizeof(double));
memset(Yn + N, 0, (R2N - N) * sizeof(double));
//哈特莱变换
FHT(Yn, R2N);
//后半部分
for (int i = 1; i < N2; i++)
{
Xn[R2N - i]._Val[0] = (Yn[i] + Yn[R2N - i]) / 2;
Xn[R2N - i]._Val[1] = (Yn[i] - Yn[R2N - i]) / 2;
}
Xn[0] = Yn[0];
Xn[N2] = Yn[N2];
//前半部分
for (int i = 1; i < N2; i++)
{
Xn[i]._Val[0] = Xn[R2N - i]._Val[0];
Xn[i]._Val[1] = -Xn[R2N - i]._Val[1];
}
}
(3)测试代码
#define SIZE 4194304
int main()
{
Complex *Xn = new Complex[SIZE];
double *Yn = new double[SIZE];
for (int i = 0; i < SIZE; i++)
{
Yn[i] = i + 1;
}
DWORD t = GetTickCount();
//FFT1(Xn, SIZE, Yn, SIZE - 100);
//FFT2(Xn, SIZE, Yn, SIZE - 100);
t = GetTickCount() - t;
printf("%ld\n", t);
delete[] Xn;
delete[] Yn;
return 0;
}
2、测试结果
FFT1运行10次时间:2641,2641,2672,2641,2610,2688,2688,2641,2640,2828
FFT2运行10次时间:3234,3203,3172,3172,3250,3219,3063,3187,3219,3250
对比可见,直接利用复数FFT算法所用时间较少,应该与程序结构有关。FFT1虽然乘法运算量较多,但结构简单,运算效率较高;FFT2虽然乘法运算量较少,但结构相对复杂,运行效率较低。由此可见,在数值计算程序设计时不光要考虑运算量与计算精度,算法结构也是不容忽视的问题。
来源:CSDN
作者:zlhex
链接:https://blog.csdn.net/zlhex/article/details/104216124