Komplexe Zahlen aus Datei einlesen



  • Wie bereits vorausgesagt habe ich natürlich jetzt ein Problem mit den komplexe Rechenoperationen...
    Einmal Vorweg: kann eine Komplexe Zahl auch als Array definiert werden?

    Hier ist mal mein Code:

    #include <fstream> 
    #include <iostream> 
    #include <complex>
    #include <math.h>
    
    using namespace std;
    
    int main(void) 
    { 
    	double re, im, reFT, imFT, test;
    	int i=0, N, p, j;
    
    	fstream count;
    	count.open("input.txt", ios::in);
    	while (!count.eof()) {
    		count >> re >> im;
    		i=i++;
    	}
    	count.close();
    
    	N=i;
    	test=i/2.0;
    	i=0;
    
    	if (test != (int)test) {
    		cout << "Ungerade Anzahl von komplexen Zahlen!";
    	}
    	else {
    
    		ifstream datei("input.txt");
    		while (!datei.eof()) {
    			datei >> re >> im;
    
    			complex<double> fj[N](re, im), fn[N](reFT, imFT), im(0.0,1.0), Sum_fn[N];
    			j=0;
    
    			for (p=-N/2; p == N/2-1; p++) {
    
    				j=j++;
    				Sum_fn[j] = Sum_fn[j-1]+exp((-2.0*3.14*im*i*p)/N)*fj[j];
    			}
    
    			fn[i] = 1.0/N*Sum_fn[i];
    
    			cout << "\nFouriertransformierte: " << fn[i] << endl;
    			i=i++;
    		}
    	}
    
    }
    


  • #include <fstream> 
    #include <iostream> 
    #include <complex>
    #include <math.h>
    #include <vector> 
    
    using namespace std;
    
    int main(void) 
    {	
      // besser statt 2 mal komplett durchzugehen:
      std::vector<std::complex<double> > daten;
    
      ifstream count ("input.txt");
      if (count.is_open())
      {  
        double re,im; // erst deklarieren wenn du sie benutzt
        while (!count.eof()) 
        { 
          count >> re >> im;
          if (count.good()) // letzte Leseoperation erfolgreich? // dann kannste das i++'en ganz knicken
            daten.push_back(std::complex<double>(re,im));
          else
            std::cout << "Ungerade Anzahl von komplexen Zahlen!";
        }
        count.close();
      }
      else 
      { 
        std::cout << "Unable to open file"; 
        return 1; 
      }
    
      std::vector<std::complex<double> > sumsums;
      sumsums.reserve(daten.size());
    
      for (int p=0; p < daten.size(); p++) 
      {
        // machwasmitdemzeug
        sumsums.push_back(daten.at(p));
      }
    }
    


  • ein paar code anmerkungen:

    #include <fstream> 
    #include <iostream> 
    #include <complex>
    #include <math.h>
    
    using namespace std;
    
    int main(void) 
    { 
    	double re, im, reFT, imFT, test;
    	int i=0, N, p, j;
    

    Zeug so spät deklarieren wie es geht

    fstream count;
    	count.open("input.txt", ios::in);
    	while (!count.eof()) {
    		count >> re >> im;
    		i=i++;
    	}
    	count.close();
    

    fstream schmeisst exceptions wenns schief geht ... ifstream auch aber dafür liefert ifstream.good() einen Anhaltspunkt ob was schief geht. i=i++ ist ziemlich Sinnbefreit, das macht in etwa : i = i; ++i; google nach Postincrement: Kurzfassung: ++irgendwas und irgendwass++ zählen irgendwas um 1 hoch .. ++irgendwas sofort wo es steht, irgendwas++ erst nach Auswertung des Ausdrucks (grob gesagt) ... ein = hat in keinem was zu suchen.

    N=i;
    	test=i/2.0;
    	i=0;
    
    	if (test != (int)test) {
    		cout << "Ungerade Anzahl von komplexen Zahlen!";
    	}
    

    warum nicht if (i%2 == 0) {...} .. kein Cast nötig und den Moludo operator sollte man kennen:

    Teste die hier mal durch 🙂

    int b=24; 
    int wieoft=b/10; 
    int rest=b%10; 
    double durch = b/10.0;
    double test = b/10;
    

    warum 2 mal Öffnen statt gleich speichern (s.o.)

    else {
    
    		ifstream datei("input.txt");
    		while (!datei.eof()) {
    			datei >> re >> im;
    
    			complex<double> fj[N](re, im), fn[N](reFT, imFT), im(0.0,1.0), Sum_fn[N];
    			j=0;
    

    reFt, imFt find ich irgendwie nicht ...achdoch gaaaaaaaaaaaaaanz oben ... aber nicht initialisiert, da steht also immer was anderes drin und du initialisiert damit gleich nen Array?

    for (p=-N/2; p == N/2-1; p++) {
    
    				j=j++;
    				Sum_fn[j] = Sum_fn[j-1]+exp((-2.0*3.14*im*i*p)/N)*fj[j];
    			}
    
    			fn[i] = 1.0/N*Sum_fn[i];
    
    			cout << "\nFouriertransformierte: " << fn[i] << endl;
    			i=i++; // Sinnbefreit, siehe oben
    		}
    	}
    }
    


  • padreigh schrieb:

    fstream schmeisst exceptions wenns schief geht ...

    ... wenn man es ihm sagt: http://www.cplusplus.com/reference/iostream/ios/exceptions/



  • Ok, dann mal langsam für die etwas Begriffsstutzigen wie mich... 😉

    std::vector<std::complex<double> > daten;

    ifstream count ("input.txt");
    if (count.is_open())
    {
    double re,im; // erst deklarieren wenn du sie benutzt
    while (!count.eof())
    {
    count >> re >> im;
    if (count.good()) // letzte Leseoperation erfolgreich? // dann kannste das i++'en ganz knicken
    daten.push_back(std::complex<double>(re,im));
    else
    std::cout << "Ungerade Anzahl von komplexen Zahlen!";
    }
    myfile.close();

    Woher weiß der Compiler jetzt dass eine gerade oder ungerade Anzahl an kompl. Zahlen in der Datei sind?

    `std::vector<std::complex<double> > sumsums;

    sumsums.reserve(daten.size());So wie ich das verstehe istdaten.size()` sozusagen die Anzahl der Zeilen mit Inhalt in meiner Datei.

    reFt, imFt find ich irgendwie nicht ...

    reFT und imFT brauche ich zur Zeit auch noch nicht. Das sollte dann später wieder in eine Datei ausgegeben werden. Es reicht bislang vollkommen aus wenn die Rechenoperationen ohne Fehler durchgeführt werden können.
    Weiters wäre auch interessant ob meine Deklaration von i im(0.0,1.0) auch so korrekt ist.
    Müssen evtl. andere Operatoren verwendet werden wenn man mit komplexen Zahlen rechnet oder erkennt der Compiler automatisch was gemeint ist wenn eine Zahl als komplexe Zahl deklariert ist?


  • Mod

    Michael E. schrieb:

    padreigh schrieb:

    fstream schmeisst exceptions wenns schief geht ...

    ... wenn man es ihm sagt: http://www.cplusplus.com/reference/iostream/ios/exceptions/

    Ich glaube Exceptions sind nicht was hier gesucht sind, eher die Grundlagen der Streambenutzung. Und vielleicht etwas Lernwille, denn der Threadersteller hat in diesem Thread schon einige Beispiele bekommen, wie man alles viel besser machen kann. Ich würde an seiner Stelle mal die erste oder zweite Antwort angucken, verstehen und als Ansatz nehmen *Wink mit dem Zaunpfahl*.


  • Mod

    Poolshark schrieb:

    Woher weiß der Compiler jetzt dass eine gerade oder ungerade Anzahl an kompl. Zahlen in der Datei sind?

    Der Compiler weiß davon gar nichts. Meinst du dein eigenes Programm? Benutze Begriffe nicht fahrlässig, das verwirrt bloß die Leser.

    `std::vector<std::complex<double> > sumsums;

    sumsums.reserve(daten.size());So wie ich das verstehe istdaten.size()` sozusagen die Anzahl der Zeilen mit Inhalt in meiner Datei.

    Nein. es ist die Anzahl der Elemente in daten. In daten wurden in dem Beispielprogramm die komplexen Zahlen aus der Datei gespeichert, ganz unabhängig von irgendwelchen Zeilen oder sonst etwas. Was du dringend brauchst ist mehr Wissen über die Streams und ganz besonders über std::vector. Das ist ungeheuer nützlich, sprengt jedoch den Rahmen dieses Forums und dürfte dich ein paar Stunden beschäftigen. Such mal nach Tutorials zu vector.

    Weiters wäre auch interessant ob meine Deklaration von i im(0.0,1.0) auch so korrekt ist.

    Wenn es eine Zahl mit Realteil 0 und Imaginärteil 1 sein soll: Ja.

    Müssen evtl. andere Operatoren verwendet werden wenn man mit komplexen Zahlen rechnet oder erkennt der Compiler automatisch was gemeint ist wenn eine Zahl als komplexe Zahl deklariert ist?

    Bevor man Sachen benutzt die man nicht kennt, ist es immer gut in einer Referenz nachzugucken:
    http://www.cplusplus.com/reference/std/complex/complex/
    Wie du siehst, kommt complex mit jeder Menge überladener Operatoren. Ob naturlich deine Rechnung richtig ist, kann ich nicht sagen, weil ich nicht zig zweibuchstabige Abkürzungen entschlüsseln will. Wenn man Kryptographiekenntnisse benötigt um ein Programm zu lesen, dann ist etwas falsch.



  • Poolshark schrieb:

    Ok, dann mal langsam für die etwas Begriffsstutzigen wie mich... 😉

    std::vector<std::complex<double> > daten; 
    
      ifstream count ("input.txt"); 
      if (count.is_open()) 
      {   
        double re,im; // erst deklarieren wenn du sie benutzt 
        while (!count.eof()) 
        { 
          count >> re >> im; 
          if (count.good()) // letzte Leseoperation erfolgreich? // dann kannste das i++'en ganz knicken 
            daten.push_back(std::complex<double>(re,im)); 
          else 
            std::cout << "Ungerade Anzahl von komplexen Zahlen!"; 
        } 
        myfile.close();
    

    Woher weiß der Compiler jetzt dass eine gerade oder ungerade Anzahl an kompl. Zahlen in der Datei sind?

    Das weiss der Comiler garnicht, aber zur Laufzeit liest du immer 2 Zahlen aus. Ob diese Leseoperation erfolgreich war sagt dir count.good() (bei Interesse einfach mal "cpp ifstream" googlen, die c++ referenz Auswählen und schaun was good() macht ...)
    Wenn das erfolgreich war, packst du die 2 Zahlen rein, sonst werden die Verworfen ... das schützt nicht vor Dateien wie

    1.01
    1.01 3.01 4.01
    2.01
    

    oder

    1 Birne
    2 Äpfel 
    4l Milch
    

    Bei ersterem würde er (1.01 + i*1.01), (3.01+i*4.01) in den Vektior packen (liegt an der Funktionsweise von <<) die letzte Zahl wird verworfen da nicht count.good(), danach folgt eof ... vielleicht solltest du statt count.eof() lieber .good() nehmen ... das wird nähmlich automatisch false wenn eof erreicht ist. Wenn du malformed input ausschließen willst brauchst du mehr Fehlerhandling ... die Einkaufsliste wird er mit einem leeren Vektor quittieren ...

    Poolshark schrieb:

    `std::vector<std::complex<double> > sumsums;

    sumsums.reserve(daten.size());So wie ich das verstehe istdaten.size()` sozusagen die Anzahl der Zeilen mit Inhalt in meiner Datei.

    Nö. daten ist der Vektor der alle korrekt geparsten complexen Zahlen deiner Datei enthält. daten.size() sagt dir wieviele Elemente der Vektor hat. (google "cpp std::vector" wähle c++ referenz, ... ) Das schöne an Vektor ist, das der das Memorymanagement für dich übernimmt, da kannst du 2 oder 2000000 complexe doublewerte Reinstecken und es tut einfach. Fast wie Magie (google "cpp STL", wähle ...). Das sumsums.reserve() ist nur nett von mir, damit sag ich "Ich brauch nen Vector mit sonsoviel Elemente, mach mal Platz" und spare mir die im Hintergrund heuristisch ermittelten Zuwachsschritte und Umkopierungen im Vektor die erfolgen würden wenn ich dies nicht täte (es würde trotzdem funktionieren, aber bei 1500293 complex Werten wird dann halt paarmal umkopiert was Zeit kosten ... )

    Poolshark schrieb:

    reFt, imFt find ich irgendwie nicht ...

    reFT und imFT brauche ich zur Zeit auch noch nicht. Das sollte dann später wieder in eine Datei ausgegeben werden. Es reicht bislang vollkommen aus wenn die Rechenoperationen ohne Fehler durchgeführt werden können.
    Weiters wäre auch interessant ob meine Deklaration von i im(0.0,1.0) auch so korrekt ist.

    Müssen evtl. andere Operatoren verwendet werden wenn man mit komplexen Zahlen rechnet oder erkennt der Compiler automatisch was gemeint ist wenn eine Zahl als komplexe Zahl deklariert ist?

    ( google "cpp std::complex constructor" wähle c++ referenz, ...)
    oder klickste: http://www.cplusplus.com/reference/std/complex/



  • So hab mich jetzt mit den Grundlagen der Streambenutzung ausführlich auseinandergesetzt. Ich denke ich hab das auch verstanden. Vielen Dank an padreigh !!! Mein Problem liegt aber immer noch in der Berechnung von komplexen Zahlen. Die Referenzen zu complex hab ich mir durchgelesen und so wie ich das verstehe kann ich Operatoren wie +,-,*,/ direkt anwenden. Auch solle die Funktion exp aus cmath funktionieren. Allerdings geht das bei meinem Programm nicht. Kann mir diesbezüglich evtl. wer weiterhelfen?

    #include <fstream> 
    #include <iostream> 
    #include <complex>
    #include <cmath>
    #include <vector>
    
    using namespace std;
    
    int main(void) { 
    
    	vector< complex<double> > original;
    
    	ifstream daten ("input.txt");
    
    	if (daten.is_open()) {
    		double re,im;
    
    		while (!daten.eof()) {
    
    			daten >> re >> im;
    			original.push_back(complex<double> (re,im));
    		}
    	}
    	else cout << "unable to open file\n";
    
    	unsigned int N;
    	N = original.size();
    
    	if (N%2 != 0) {
    		cout << "ungerade Anzahl von komplexen Zahlen!\n";
    		return 1;
    	}
    
    	vector< complex<double> >  fourier;
    	int j,n=-N/2;
    	complex<double> sum, im = (0.0,1.0);
    
    	for (int p=0; p < N; p++) {
    
    		j = -N/2;
    		sum = (0.0,0.0);
    
    		for (int q = 0; j < N; q++) {
    
    			sum = sum + exp((-2.0*3.14*j*M_PI*n*im)/N) * original[q];
    			++j;
    		}
    
    		fourier.push_back(complex<double> (1.0/N*sum));
    
    		++n;
    	}
    
    	for (int i=0; i < N; i++) {
    
    		cout << "Original: " << original[i] << "\n";
    		cout << "Transfor: " << fourier[i] << "\n";
    	}
    
    	return 0;
    
    }
    

    Besonders von Interesse ist hier Folgender Teil:

    for (int q = 0; j < N; q++) {
    
    			sum = sum + exp((-2.0*3.14*j*M_PI*n*im)/N) * original[q];
    			++j;
    		}
    

    Hier ist sum und original[q] eine komplexe Zahl. Die Exponetialfunktion besteht aus einem reellen und komplexen Teil. Weiß der Compiler (dieses Mal wird dies wohl hoffentlich der richtige Begriff sein) was er da machen soll oder nicht? Denn wenn ich das Ganze wieder in Realteil und komplexen Teil trennen muss, verstehe ich nicht was die Deklaration einer komplexen Zahl bringt.



  • Poolshark schrieb:

    .. Allerdings geht das bei meinem Programm nicht.

    .. das ist keine ausreichende Fehlerbeschreibung!

    Poolshark schrieb:

    Kann mir diesbezüglich evtl. wer weiterhelfen?

    for (int p=0; p < N; p++) {
    		
    		j = -N/2; // <=== Zeile 40
    		sum = (0.0,0.0);
    

    Zeile 40 liefert einen falschen Wert, da N unsigned int ist. Besser: j=-int(N)/2;

    Poolshark schrieb:

    Besonders von Interesse ist hier Folgender Teil:

    for (int q = 0; j < N; q++) {
    			
    			sum = sum + exp((-2.0*3.14*j*M_PI*n*im)/N) * original[q];
    			++j;
    		}
    

    Hier ist sum und original[q] eine komplexe Zahl. Die Exponetialfunktion besteht aus einem reellen und komplexen Teil. Weiß der Compiler (dieses Mal wird dies wohl hoffentlich der richtige Begriff sein) was er da machen soll oder nicht? Denn wenn ich das Ganze wieder in Realteil und komplexen Teil trennen muss, verstehe ich nicht was die Deklaration einer komplexen Zahl bringt.

    ja - das sollte genauso funktionieren, wie bei double. Eine Trennung ist normalerweise nicht notwendig.

    Bist Du sicher, dass Deine Formel stimmt? 3.14*M_PI sieht irgendwie komisch aus.



  • Nur um das Thema abzuschließen. Das Programm funktioniert nun auch wenn es sich doch als etwas schwierig heraus stellte mit komplexen Zahlen zu rechnen!

    Vielen herzlichen Dank an alle Helfer!!!

    Poolshark

    //			DISCRETE FOURIER TRANSFORMATION
    //
    //				by ***************
    //				  *******
    //					11.10.2010
    // ****************************************
    // 
    // Define PHASE in MAIN
    // Note: it need to be an even number!
    //
    // ****************************************
    
    #include <fstream> 
    #include <iostream> 
    #include <complex>
    #include <cmath>
    #include <vector>
    
    using namespace std;
    
    ///////////////////////////////////////////////////////////////				Function Fourier Transformation
    vector< complex <double> > transformation (int N, vector< complex<double> > data, int phase, int mode) {
    
    	vector< complex<double> > transform;
    	complex<double> sum;
    
    	int j, n = -N/2 + phase;
    
    	if (mode == 1) {									// Forward Transformation
    
    		for (int p=0; p < N; p++) {
    
    			j = -N/2;
    			sum = (0.0,0.0);
    
    			for (int q = 0; q < N; q++) {
    
    				sum = sum + (cos(2.0*j*n*M_PI/N)-complex<double>(0.0,sin(2.0*j*n*M_PI/N))) * data[q];
    
    				++j;
    			}
    
    			transform.push_back (1.0/N*sum);
    
    			++n;
    		}
    	}
    	else {
    
    		for (int p=0; p < N; p++) {						// Backward Transformation
    
    			j = -N/2;
    			sum = (0.0,0.0);
    
    			for (int q = 0; q < N; q++) {
    
    				sum = sum + (cos(2.0*j*n*M_PI/N)+complex<double>(0.0,sin(2.0*j*n*M_PI/N))) * data[q];
    
    				++j;
    			}
    
    			transform.push_back (sum);
    
    			++n;
    		}
    	}
    
    	return transform;
    }
    ///////////////////////////////////////////////////////////////			END	Function Fourier Transformation
    
    int main(void) {												       // START MAIN
    
    	// ****************************************
    	int phase = 6;		        // Define PHASE
    	// ****************************************
    
    	if (phase%2 != 0) {
    		cout << "Invalid value of PHASE!" << endl;
    		return 1;
    	}
    
    	//////////////////////////////////////////////////////	           // Read file
    	vector< complex<double> > original;
    	ifstream daten ("input.txt");
    
    	if (daten.is_open()) {
    		double re,im;
    
    		while (!daten.eof()) {
    
    			daten >> re >> im;
    			original.push_back(complex<double> (re, im));
    		}
    	}
    	else cout << "unable to open file" << endl;
    
    	int N;
    	N = (int) original.size();
    
    	if (N%2 != 0) {
    		cout << "file doesn't contain an even number of objects!" << endl;
    		return 1;
    	}
    
    	//////////////////////////////////////////////////////	           // Fourier Transformation
    	vector< complex<double> > fourier;					
    	fourier = transformation(N, original, 0, 1);
    	//////////////////////////////////////////////////////
    
    	//////////////////////////////////////////////////////	           // Back Transformation
    	vector< complex<double> > back;					
    	back = transformation(N, fourier, 0, 2);
    	//////////////////////////////////////////////////////
    
    	//////////////////////////////////////////////////////	           // Phase
    	vector< complex<double> > phase_vec;
    	else phase_vec = transformation(N, original, phase, 1);
    	//////////////////////////////////////////////////////
    
    	//////////////////////////////////////////////////////	           // Return Phase
    	vector< complex<double> > return_phase_vec;
    	return_phase_vec = transformation(N, fourier, phase, 2);
    	//////////////////////////////////////////////////////
    
    	//////////////////////////////////////////////////////	           // Return solution
    	for (int i=0; i < N; i++) {
    
    		cout << "---------------------------------------" << endl;
    		cout << "Original: " << original[i] << endl;
    		cout << "Transfor: " << fourier[i] << endl;
    		cout << "Back: " << back[i] << endl;
    		cout << "Phase: " << phase_vec[i] << endl;
    		cout << "Return Phase: " << return_phase_vec[i] << endl;
    	}
    
    	return 0;
    }
    

    P.S.: Ich hoffe der Code ist einigermaßen C++ gerecht... 😉


Anmelden zum Antworten