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
undirgendwass++
zählenirgendwas
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 ist
daten.size()` sozusagen die Anzahl der Zeilen mit Inhalt in meiner Datei.reFt, imFt find ich irgendwie nicht ...
reFT
undimFT
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 iim(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?
-
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*.
-
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 ist
daten.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 wie1.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 ist
daten.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 ...). Dassumsums.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
undimFT
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 iim(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 zucomplex
hab ich mir durchgelesen und so wie ich das verstehe kann ich Operatoren wie+,-,*,/
direkt anwenden. Auch solle die Funktionexp
auscmath
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
undoriginal[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
undoriginal[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...