无法将complex<double>转换为double。

3
我正在尝试修复一个程序,使其接受不同于测试值的数值。该程序应该能够接受一个表示数学函数信号的值数组,并输出该信号的快速傅里叶变换结果。以下是我已经修复的代码部分:
#include <complex>
#include <iostream>
#include <valarray>

#define fnc(x) (x)

const double PI = 3.141592653589793238460;

typedef std::valarray<double> CArray;

union{
    double d;
    int i;
}num,i;


void fft(CArray& x)
{
    const size_t N = x.size();
    if (N <= 1) return;

    // divide
    CArray even = x[std::slice(0, N/2, 2)];
    CArray  odd = x[std::slice(1, N/2, 2)];

    // conquer
    fft(even);
    fft(odd);

    // combine
    for (size_t k = 0; k < N/2; ++k)
    {
        double t = std::polar(1.0, -2 * PI * k / N) * odd[k];
        x[k    ] = even[k] + t;
        x[k+N/2] = even[k] - t;
    }
}
    //Complex f = 1.0 / sqrt(N);
    //for (unsigned int i = 0; i < N; i++)
    //  x[i] *= f;

int main()
{
    num.d=513;
    double test[num.i];
    for(i.i=1; i.i < num.i;++i.i)
        test[i.i] = (double)fnc(i.i);
    CArray data(test, num.d);

    // forward fft
    fft(data);

    std::cout << "fft" << std::endl;
    for (i.i = 0; i.i < num.i; ++i.i)
    {
        std::cout << data[i.i] << std::endl;
    }
    return 0;
}

当我尝试编译它时,它显示以下内容:

错误:在初始化中无法将 'std::complex' 转换为 'double'|

在第34行上,在此部分中标记的行上:

    for (size_t k = 0; k < N/2; ++k)
    {
        double t = std::polar(1.0, -2 * PI * k / N) * odd[k];
        x[k    ] = even[k] + t;
        x[k+N/2] = even[k] - t;
    }

这是需要翻译的内容:

请看这个例子:

        double t = std::polar(1.0, -2 * PI * k / N) * odd[k];

如果有人能告诉我如何修复它,我会非常感激。 为了更好的参考,这是原始代码,如果有人能告诉我更好的修复方法,使其实现我想要的效果。
#include <complex>
#include <iostream>
#include <valarray>
 
const double PI = 3.141592653589793238460;
 
typedef std::complex<double> Complex;
typedef std::valarray<Complex> CArray;
 
// Cooley–Tukey FFT (in-place, divide-and-conquer)
// Higher memory requirements and redundancy although more intuitive
void fft(CArray& x)
{
    const size_t N = x.size();
    if (N <= 1) return;
 
    // divide
    CArray even = x[std::slice(0, N/2, 2)];
    CArray  odd = x[std::slice(1, N/2, 2)];
 
    // conquer
    fft(even);
    fft(odd);
 
    // combine
    for (size_t k = 0; k < N/2; ++k)
    {
        Complex t = std::polar(1.0, -2 * PI * k / N) * odd[k];
        x[k    ] = even[k] + t;
        x[k+N/2] = even[k] - t;
    }
}
 
// Cooley-Tukey FFT (in-place, breadth-first, decimation-in-frequency)
// Better optimized but less intuitive
// !!! Warning : in some cases this code make result different from not     optimased version above (need to fix bug)
// The bug is now fixed @2017/05/30 
void fft(CArray &x)
{
    // DFT
    unsigned int N = x.size(), k = N, n;
    double thetaT = 3.14159265358979323846264338328L / N;
    Complex phiT = Complex(cos(thetaT), -sin(thetaT)), T;
    while (k > 1)
    {
        n = k;
        k >>= 1;
        phiT = phiT * phiT;
        T = 1.0L;
        for (unsigned int l = 0; l < k; l++)
        {
            for (unsigned int a = l; a < N; a += n)
            {
                unsigned int b = a + k;
                Complex t = x[a] - x[b];
                x[a] += x[b];
                x[b] = t * T;
            }
            T *= phiT;
        }
    }
    // Decimate
    unsigned int m = (unsigned int)log2(N);
    for (unsigned int a = 0; a < N; a++)
    {
        unsigned int b = a;
        // Reverse bits
        b = (((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1));
        b = (((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2));
        b = (((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4));
        b = (((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8));
        b = ((b >> 16) | (b << 16)) >> (32 - m);
        if (b > a)
        {
            Complex t = x[a];
            x[a] = x[b];
            x[b] = t;
        }
    }
    //// Normalize (This section make it not working correctly)
    //Complex f = 1.0 / sqrt(N);
    //for (unsigned int i = 0; i < N; i++)
    //  x[i] *= f;
}
 
// inverse fft (in-place)
void ifft(CArray& x)
{
    // conjugate the complex numbers
    x = x.apply(std::conj);
 
    // forward fft
    fft( x );
 
    // conjugate the complex numbers again
    x = x.apply(std::conj);
 
    // scale the numbers
    x /= x.size();
}
 
int main()
{
    const Complex test[] = { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 };
    CArray data(test, 8);
 
    // forward fft
    fft(data);
 
    std::cout << "fft" << std::endl;
    for (int i = 0; i < 8; ++i)
    {
        std::cout << data[i] << std::endl;
    }
 
    // inverse fft
    ifft(data);
 
    std::cout << std::endl << "ifft" << std::endl;
    for (int i = 0; i < 8; ++i)
    {
        std::cout << data[i] << std::endl;
    }
    return 0;
}

补充说明,如果有人知道更好的代码符合我的需求,我也可以使用它。


1
使用 math.h 中的 M_PI,而不是定义自己的常量。 - phuclv
@phuclv:math.h不是C++标准库的一部分。C++标准库没有定义pi常量。如果包含math.h导致定义了M_PI宏,那么你就依赖于编译器特定的行为。 - Cris Luengo
2个回答

1

std::complex<double>double是不兼容的类型。

请将其更改为:

double t = std::polar(1.0, -2 * PI * k / N) * odd[k];

转换为:

std::complex<double> t = std::polar(1.0, -2 * PI * k / N) * odd[k];

由于std::polar返回:

由rho和theta形成的极坐标格式的复数笛卡尔等价形式。


谢谢,它实际上起作用了,但现在它在接下来的两行中显示了一个新的错误:error: cannot convert 'std::complex<double>' to 'double' in assignment| - Felipe Tafoya Loeza
@FelipeTafoyaLoeza 因为您使用了 typedef std::valarray<double> CArray;,而不是一些兼容的东西,例如使用 Complex 而不是 double。希望这可以帮助您!=) - gsamaras

0
错误信息很明显:std::polar返回的是std::complex,而不是double。看看代码的其他部分,也许只需要改变t的类型?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接