Komplexe Zahlen aus Datei einlesen



  • VF schrieb:

    padreigh schrieb:

    c++ vector (std::vectorstd::complex >)

    [...] Daten unbekannter Größe [...] std::deque ist doch viel besser geeignet.

    Bei mir: Gewohnheit, habe mit Vector mehr gearbeitet. Im Normalfall pack ich da ein std::vector<Whatever>.reserve(amount); davor und vermeide damit re-allocs. 😉



  • kommt halt drauf an - aber anhören tut es sich erst mal so, als ob das einlesen relativ zeitunkritisch passieren würde - außerdem sind 8Byte pro Objekt jetzt nicht so unendlich viel zu kopieren, dass es die x zusätzlichen new`s und die langsamere iteration rechtfertigen würde.
    außerdem ists ja nicht so, dass die eingabe aus nem wahnsinnig schnellen medium ausgelesen werden würde - nein, sie kommt von ner festplatte...

    bb


  • Administrator

    1. Man liest einmal ein. Es müssten schon verdammt viele Zahlen sein, bis man hier überhaupt einen Geschwindigkeitsnachteil hat. Dafür hat man wirklich schnellen Zugriff auf die Daten.
    2. Ein std::vector vergrössert sich auch nicht immer nach jedem push_back . Somit braucht es wahrscheinlich nur ein paar mal eine neue Speicherreservierung mit Kopien.
    3. Falls man wirklich grössere Datenmenge lädt, kann man womöglich eine Abschätzung machen, wieviele es sein werden, und dann std::vector::reserve verwenden.

    In den meisten Fällen ist std::vector völlig ausreichend.

    Grüssli



  • Und ich meine. Bleibt der Flaschenhals nicht egal bei welchem Container hier in jedem Fall das Dateisystem? Dann ist die Diskussion nämlich von vornerein erschlagen.


  • Mod

    Außerdem hatten wir hier im Forum schon zigmal das Thema deque vs. vector mit zahlreichen Benchmarks diskutiert. Mal nach suchen. vector hat jedenfalls immer klar vorne gelegen außer in ganz speziellen Fällen.



  • So, ich habe jetzt ein bisschen herumexperimentiert...
    Leider funktioniert (zumindest bei mir) der 1. angegebene Code nicht. Vielleicht hat es ja was mit meiner Entwicklerumgebung zu tun (ich benutze XCode).
    Anyway, ich kann mittlerweile Zahlen aus einem File mittels ifstream auslesen allerdings geht das immer nur für eine Zeile? Wie kann man nun alle Zeilen auslesen?

    Hier der Code:

    #include <fstream> 
    #include <iostream> 
    #include <complex>
    
    using namespace std;
    
    int main() 
    { 
    
    	int a,b;
    
    	ifstream datei("input.txt");
    
        for( int c, d; datei >> c >> d; ) {
    
    	//datei >> c >> d;
    
    	a=c+1;
    	b=d+1;
    
    	cout << "Test: ";
    	cout << a << b;
    	cout << " orginal: ";
    	cout << c << d;
    	cout << "\n";
    
    	}
    
    }
    

    Die Ausgabe beschränkt sich auf folgendes:
    Test: 44 orginal: 34

    In meiner Testdatei "input.txt" befinden sich 3 Zeilen mit folgenden Werten:
    `3 4

    5 6

    7 8`

    Vielen Dank für die vielen prompten Antworten!


  • Mod

    Poolshark schrieb:

    So, ich habe jetzt ein bisschen herumexperimentiert...
    Leider funktioniert (zumindest bei mir) der 1. angegebene Code nicht.

    Was meinst du mit funktioniert nicht?

    Vielleicht hat es ja was mit meiner Entwicklerumgebung zu tun (ich benutze XCode).

    Sehr unwahrscheinlich, denn der Code ist absolut in Ordnung und es ist sehr, sehr ungewöhnlich Fehler in Entwicklungsumgebungen zu finden. Besonders bei solch kleinen Progrämmchen.

    Anyway, ich kann mittlerweile Zahlen aus einem File mittels ifstream auslesen allerdings geht das immer nur für eine Zeile? Wie kann man nun alle Zeilen auslesen?

    Das sollte so eigentlich auch funktionieren. Bei mir liefert dein Programm auch ein vollständiges Ergebnis:

    Test: 23 orginal: 12
    Test: 45 orginal: 34
    Test: 67 orginal: 56
    Test: 89 orginal: 78
    

    input.txt:

    1 2
    3 4
    5 6
    7 8
    

    Mir fällte jedoch auf, dass dein Programm schon falsch rechnet, weil die 4 nicht um eins erhöht wurde. Daher vermute ich mal, dass du mit einem etwas anderem Programm gearbeitet hast als das hier gezeigte.



  • probiere mal spaßeshalber ab Zeile 14

    char black_magic;
        for( int c, d; datei >> c >> d >> black_magic; ) {
    

    .. und sage uns was passiert



  • Also ich habe den Code nun etwas verändert:

    #include <fstream> 
    #include <iostream> 
    #include <complex>
    
    using namespace std;
    
    int main(void) 
    { 
    
    	int a,b,c,d;
    
    	ifstream datei("input.txt");
    
        while (!datei.eof()) {
    		datei >> c >> d;
    		a=c+1;
    		b=d+1;
    
    		cout << "Test: ";
    		cout << a << b;
    		cout << " orginal: ";
    		cout << c << d;
    		cout << "\n";
    	}
    
    }
    

    Leider beschränkt sich die Ausgabe immer noch auf eine Zeile:
    `Last login: Tue Oct 5 16:42:33 on ttys000

    /Users/florianragossnig/Documents/Uni/Computational\ Physics/Programme/Fourier/build/Debug/Fourier ; exit;

    Florian-Ragossnigs-MacBook-Pro:~ florianragossnig$ /Users/florianragossnig/Documents/Uni/Computational\ Physics/Programme/Fourier/build/Debug/Fourier ; exit;

    Test: 45 orginal: 34

    logout

    [Process completed]`

    Immerhin rechnet das Programm jetzt richtig...
    Ich denke nicht dass es an der Entwicklungsumgebung generell liegt, aber evtl. verwende ich den falschen Compiler (obwohl ich ein C++ Projekt gestartet habe)!

    Bei Abänderung des Codes zu dem Beitrag von Werner passiert, kurz und knapp, garnichts:
    `Last login: Tue Oct 5 16:44:09 on ttys000

    /Users/florianragossnig/Documents/Uni/Computational\ Physics/Programme/Fourier/build/Debug/Fourier ; exit;

    Florian-Ragossnigs-MacBook-Pro:~ florianragossnig$ /Users/florianragossnig/Documents/Uni/Computational\ Physics/Programme/Fourier/build/Debug/Fourier ; exit;

    logout

    [Process completed]`



  • Aus Performancegründen solltest du die Zahlen binär speichern außer die Speicherung als ASCII ist unbeding erforderlich...



  • wie gesagt sollte der code aber richtig sein...
    bist du mal mit dem debugger durchgegangen?

    bb

    edit: @icematrix: gut, dass das jz richtig viel mit dem Thema zu tun hat... 4 Zahlenpaare... stimmt - da kann man einige Stunden Rechenzeit sparen...


  • Mod

    Icematix schrieb:

    Aus Performancegründen solltest du die Zahlen binär speichern außer die Speicherung als ASCII ist unbeding erforderlich...

    Aus Portabilitätsgründen solltest du die Zahlen als ASCII speichern, außer die Speicherung als binär ist unbeding erforderlich...


  • Mod

    Poolshark schrieb:

    Bei Abänderung des Codes zu dem Beitrag von Werner passiert, kurz und knapp, garnichts:

    Es scheint mir, deine Eingabedatei hat nur eine Zeile. Überprüfe diese Möglichkeit. Vielleicht liest du versehentlich die falsche Datei ein. Ändere mal die Datei von der du meinst, dass sie eingelesen wird und guck, ob die Änderungen Auswirkungen auf das Programm haben.



  • Hab den Fehler gefunden: Die von Xcode produzierte executable funktioniert aus irgendwelchen Gründen nicht... Wenn ich das Programm in der Debugger Console laufen lasse bekomme ich die richtigen Lösungen. Da ich keine Ahnung habe was XCode da alles macht und da der Code zu stimmen scheint, dürfte dies vorerst ausreichen.

    Vielen Dank für Eure Hilfe ( es könnte sein dass ich mich bezüglich der komplexen Rechenoperationen nocheinmal an euch wenden muss 😉 )!



  • 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*.


Anmelden zum Antworten