2016-05-22 12 views
-1

Ich benutze getline, um Eingaben von einer Datei (myfile.txt) von meinem zu erhalten Computer enthält die Datei folgende Werte: 1 1 1 1 0 0 0 0. Jeder dieser Werte wird in ein Array x [n] eingegeben, das später als Eingabe für mein schnelles Fourier-Transformationsprogramm verwendet wird. jedoch, wenn ich das Programm ausführen, ist die Ausgabe ein bisschen anders als das ursprüngliche Programm, dh. denjenigen, der die Array-Wert erklärte direkt innerhalb des Programms (const komplexer Test [] = {1,0, 1,0, 1,0, 1,0, 0,0, 0,0, 0,0, 0,0};) hatVerwenden von getline in C++, um das contain (integer) aus einer Datei zu erhalten und sie in ein Array einzugeben, das als Eingabe für ein C++ fft-Programm verwendet wird

//original code 
    #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 
    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);`enter code here` 

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

//new modified code 
#include <complex> 
#include <iostream> 
#include <valarray> 
#include <malloc.h> 
#include <string> 
#include <stdlib.h> 
#include <fstream> 
#include <cstdio> 
#include <cstdlib> 

using namespace std; 
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 
/* 
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; 
     } 
    } 

} */ 
// 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() 

{ 

    int n=0; 
    int b=0; 
    int q=0; 
    int i; 
    int Nx=0; 
    //double *x; 
     double x [8]; 
    /**************************************************** getting x ********************************************/ 

     string line; 
     double Result; 
      ifstream myfile ("myfile.txt"); 
      if (myfile.is_open()) 
       { 
       for (i = 0 ; (i < 8) && (myfile >> x[i]) ; ++i) 

      cout << line << '\n'; 
       stringstream convert(line); 

       if (!(convert >> Result)) 
       Result = 0; 

       x[i]=Result; 

       } 
      else cout << "Unable to open file"; 
    /****************************************************************************************************************/ 


    Complex test[8];  
    for (i = 0 ; i < 8 ; ++i) 
    test[i] = x[i]; 

    CArray data(test, 8); 

    // forward fft 
    fft(data); 

    std::cout << "fft" << std::endl; 
    for (int i = 0; i < 8; ++i) 
    { 
     cout << data[i] << 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; 
} 



The purpose of this task is to calculate the FFT (Fast Fourier Transform) of an input se 

quence

+0

Sie können (und sollten) Ihre Frage bearbeiten, anstatt sie zu kommentieren, um sie zu verdeutlichen. Aber nehmen Sie sich die Zeit, um die Richtlinien der Website zu lesen. Insbesondere wird Ihre Frage außerhalb des Themas behandelt, da Sie Ihr Problem nicht auf ein minimales, aber vollständiges Beispiel reduziert haben. –

Antwort

0

Es gibt (mindestens) drei Punkte in Ihrem modifizierten Code zu korrigieren.

(1) Sie verwenden 16 wo (wenn ich nicht falsch liege) sollten Sie 8 verwenden; x sollte new double[8] (oder double x[8]? Warum verwenden Sie ein dynamisches Array?); testComplex test[8]; sein sollte, sollte CArray data(test, 16); sein CArray data(test, 8);

(2) Sie nicht initialisieren i in der Lesedatei Schleife; Wenn Sie also schreiben

x[i]=(double)Result; 

ist der Wert i nicht definiert. Wenn also i im Bereich [0,16 [liegt, verlieren Sie die ersten 7 Werte und der achte Wert ist in x[i]; Die anderen Werte von x sind nicht definiert. Wenn i außerhalb des Bereichs [0,16] liegt, kann das Programm abstürzen.

En passant: x[i] und Result sind double; also ist die Besetzung überflüssig.

Ich nehme an Ihr Zyklus sein sollte (wir erinnern uns nur 8 Werte haben) so etwas wie

for (i = 0 ; (i < 8) && getline(myfile, line) ; ++i) 
    { 
    cout << line << '\n'; 
    stringstream convert(line); 

    if (!(convert >> Result)) 
     Result = 0; 

    x[i]=Result; 
    } 

(3) Ich verstehe nicht, was

const Complex test[16] = x[i]; 

sein sollte ich Ihre Absicht vermuten war

Complex test[8];  
for (i = 0 ; i < 8 ; ++i) 
    test[i] = x[i]; 

---- ---- EDIT

Korrektur: ein richtiger Weg, um die Datei zu laden, kann

// double Result; 
ifstream myfile ("myfile.txt"); 
if (myfile.is_open()) 
{ 
    for (i = 0 ; (i < 8) && (myfile >> x[i]) ; ++i 
    ; 

    // no need for myfile.close() (take care of it the destructor) 
} 
else cout << "Unable to open file"; 

Leider sein.

+0

Hallo Max, danke für deine Empfehlung, ich habe den Code wie du vorgeschlagen geändert, allerdings ist das immer noch anders als beim ursprünglichen Programm, ich habe das geänderte Programm durch das neue ersetzt, ich habe auch das neue Ergebnis hinter mir. – Serge

+0

@ Serge - es ist meine Schuld, sorry: korrigiert meine Antwort – max66

+0

Max, es funktioniert jetzt !!! Danke für deine Hilfe, ich habe meinen vorherigen Beitrag noch einmal mit dem richtigen Code geändert.Wer weiß, vielleicht hat jemand das gleiche Problem wie ich heute in der Zukunft – Serge