实数快速傅里叶变换

实数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虽然乘法运算量较少,但结构相对复杂,运行效率较低。由此可见,在数值计算程序设计时不光要考虑运算量与计算精度,算法结构也是不容忽视的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值