2017-06-09 83 views
0

我正在尝试修复一个我发现的程序,因此它需要的值与它作为自身测试的值不同。程序应该能够获取一系列值,这些值将数学函数表示为信号,输出应该是对该信号的快速傅立叶变换。以下是我已经有固定的代码:无法将复杂的<double>转换为双倍

#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; 
} 

当我尝试编译TI显示我在34行的样带

error: cannot convert 'std::complex' to 'double' in initialization|

,就标志着这部分行:

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; 
    } 

pesizaly这一个:

 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; 
} 

Ps。如果有人知道我需要的更好的代码,我也可以使用它。

+1

使用['M_PI'在math.h中](HTTPS://计算器.com/q/1727881/995714)而不是定义你自己的 –

回答

0

错误消息非常明确:std::polar返回std::complex,而不是double。看其余的代码,也许只是改变t的类型?

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回报:

The complex cartesian equivalent to the polar format formed by rho and theta.

+0

谢谢,它真的有用,但现在它显示了一个新的错误e后面跟着两行:'错误:无法将'std :: complex '转换为赋值|中的'double'。 –

+0

@FelipeTafoyaLoeza,因为你使用'typedef std :: valarray CArray;',而不是兼容的,例如使用'Complex'而不是'double'。希望有所帮助! =) – gsamaras