Polynominterpolation: gnuplot einbinden und Stützpunktwechsel



  • Hallo,

    ich bin neu hier im Forum und genauso neu beim c++ programmieren.

    Ich bin enorm begeister, dass ich folgendes Programm tatsächlich selbständig hinbekommen habe, allerdings muss ich noch 2 Sachen machen, die ich allein nicht bewerkstelligt kriege.

    Hier erstmal mein Programm:

    #include<iostream>
    using namespace std;
    
    double interpolate(double x0, double x1, double y0, double y1, double xtarget)
    	{
    		return ((xtarget-x0)*y1-(xtarget-x1)*y0)/(x1-x0);
    	}
    
    int main()
    	{
        cout.setf(ios::fixed, ios::floatfield);		//Fixed format
    
    	double p[2][101];
    	double x[2][10];
    	double y[2][10];
    	double aa;
    	double nn;
    	int n;
    	int a;
    	int b;
    	int c;
    	int d;
    
    	for(n=2; n<=5; n++)
    	{
    		nn=2*n;
    
    	for(a=0; a<=100; a++)
    	{
    		aa=a;
    		p[0][a]=(aa/10)-5;
    
    		for(b=0; b<=nn; b++)
    		{
    			x[0][b]=10*b/nn;
    			y[0][b]=1/(1+x[0][b]*x[0][b]);
    		}
    
    		for(c=0; c<=nn-1; c++)
    		{
    			for(d=0; d<=nn-c-1; d++)
    			{
    				y[0][d]= interpolate(x[0][d], x[0][d+c+1], y[0][d], y[0][d+1], p[0][a]);
    			}
    		}
    	p[1][a]=y[0][0];
    	cout<<"\nx ist "<<p[0][a];
    	cout<<"\ny ist "<<p[1][a];
    
    	}
    
    	cout<<"\n Das Ergebnis ist "<<p[1][95];
    
    	}
        return 0;
    	}
    

    Nun zu meinen Fragen 🙂

    1. Die Zeile 11 hab ich nur so aus einem Quellcode mitkopiert, genau wie Zeile 1 und 2. Ich habe es mal rausgenommen und bemerkt, dass es was mit der Ausgabelänge zu tun hat. Gerechnet wird in meinem Programm aber schon mit der "double" länge, so wie ich die Variablen auch initialisiert habe oder?

    3. Ich müsste genau das Programm nochmal mit anderen Stützpunkten durchlaufen lassen. Allerdings fehlt mir da etwas die Idee, wie ich das am besten bewerkstellige. Ich muss die schleife für die Stützpunkte ja innerhalb der Schleife mit der Variablen "a" haben, da ich sie ja innerhalb der anderen Schleifen überschreibe. Kann ich vielleicht die Schleife der Stützpunkte, also die mit der Variablen "b" so Programmieren, dass ich auf eine ausgelagerte Routine (so wie mein "interpolate" vor dem "main") zugreife und da 2 verschiedene berechnungen mache?
    Die anderen Stützpunkte hätte die gleiche berechnung wie Zeile 37 für y[0][b], die Zeile 36 müsste aber folgende Formel nutzen: 5cos((2b+1)/(2nn-1))

    Wäre wirklich super, wenn mir da jemand helfen könnte.

    Bis dann, Till



  • liebero3 schrieb:

    Hallo,

    ich bin neu hier im Forum und genauso neu beim c++ programmieren.

    Ich bin enorm begeister, dass ich folgendes Programm tatsächlich selbständig hinbekommen habe, allerdings muss ich noch 2 Sachen machen, die ich allein nicht bewerkstelligt kriege.

    Hier erstmal mein Programm:

    #include<iostream>
    using namespace std;
    
    double interpolate(double x0, double x1, double y0, double y1, double xtarget)
    	{
    		return ((xtarget-x0)*y1-(xtarget-x1)*y0)/(x1-x0);
    	}
    
    int main()
    	{
        cout.setf(ios::fixed, ios::floatfield);		//Fixed format
    
    	double p[2][101];
    	double x[2][10];
    	double y[2][10];
    	double aa;
    	double nn;
    	int n;
    	int a;
    	int b;
    	int c;
    	int d;
    
    	for(n=2; n<=5; n++)
    	{
    		nn=2*n;
    
    	for(a=0; a<=100; a++)
    	{
    		aa=a;
    		p[0][a]=(aa/10)-5;
    
    		for(b=0; b<=nn; b++)
    		{
    			x[0]=10*b/nn;
    			y[0][b]=1/(1+x[0][b]*x[0][b]);
    		}
    
    		for(c=0; c<=nn-1; c++)
    		{
    			for(d=0; d<=nn-c-1; d++)
    			{
    				y[0][d]= interpolate(x[0][d], x[0][d+c+1], y[0][d], y[0][d+1], p[0][a]);
    			}
    		}
    	p[1][a]=y[0][0];
    	cout<<"\nx ist "<<p[0][a];
    	cout<<"\ny ist "<<p[1][a];
    
    	}
    
    	cout<<"\n Das Ergebnis ist "<<p[1][95];
    
    	}
        return 0;
    	}
    

    **

    Nun zu meinen Fragen 🙂

    1. Die Zeile 11 hab ich nur so aus einem Quellcode mitkopiert, genau wie Zeile 1 und 2. Ich habe es mal rausgenommen und bemerkt, dass es was mit der Ausgabelänge zu tun hat. Gerechnet wird in meinem Programm aber schon mit der "double" länge, so wie ich die Variablen auch initialisiert habe oder?

    Wäre wirklich super, wenn mir da jemand helfen könnte.

    Bis dann, Till**

    Zeile 1 bindet die input und output stream Headerdatei ein. Diese dient der Ein- und Ausgabe auf der Konsole. Es gibt noch weitere solcher Headerdateien. http://de.wikipedia.org/wiki/Header-Datei

    Zeile 2 macht den Namespace std bekannt. Dadurch brauchst du nicht immer std::cout zu schreiben, sondern es reicht cout. http://tutorial.schornboeck.net/namespace.htm

    Zeile 11 gibt das Ausgabeformat an. Deine Rechnungen werden also intern trotzdem mit der Genauigkeit von double ausgeführt. Es beeinflusst nur die Ausgabe.

    Dateien kannst du mit fstream schreiben. Näheres dazu findest du auch im Internet in einem beliebigem Tutorial.

    Wie du gnuplot ansteuerst, weiß ich leider nicht - habe es nie benutzt. Eventuell findest du aber auch dazu etwas im Internet.



  • Hi iuojkl,
    danke für die Erklärungen zu Frage 1 und dem Stichwort fstream.

    Habe mir das fstream jetzt mal angesehen und folgendes frage ich mich jetzt:

    Ich möchte ja in meiner n-Schleife die Werte ausgeben. Da n sich auf die Anzahl meiner Stützpunkte bezieht, wäre es möglich dieses "n" mit in den Dateinamen zu bringen? habe im Internet den Beispielcode gefunden:

    ofstream myfile;
      myfile.open ("example.txt");
      myfile << "Writing this to a file.\n";
      myfile.close();
    

    wenn ich das richtig verstehe ist also eine vorhandene Datei öffnen das gleiche wie eine neue Datei erstellen, sofern sie noch nicht existiert. Wäre es da möglich sie je nachdem welchen Wert mein "n", bzw mein "nn" die Datei stuetzpunkte_n="nn".text zu erstellen/öffnen? wobei "nn" der Wert von n sein sollen.

    Da ich wirklich absoluter Neuling im programmieren bin, wäre es möglich, dass mir jemand den Teil implementiert? habe ein bischen damit rumgespielt, aber nichts funktionierendes zustande gebracht.
    Für meine Aufgabe ist das ja auch kein elementarer Teil, hab das wichtige ja selbst geschafft. Hauptsächlich geht ja ja um den Algorithmus, ist eine Aufgabe für Numerik.

    MfG Till



  • So ich habe mein Programm jetzt selbstständig schon sehr weit.

    Es wäre wirklich super toll und für mich auch enorm wichtig, wenn mir einer noch bei folgenden Problemen helfen könnte.

    Hier ist mein code:

    #include<iostream>
    #include <fstream>
    #include <stdio.h>
    #include <math.h>
    #include <sstream>
    #define PI 3.14159265
    using namespace std;
    
    double interpolate(double x0, double x1, double y0, double y1, double xtarget)
    {
    	return ((xtarget-x0)*y1-(xtarget-x1)*y0)/(x1-x0);//meine funktion fŸr die interpolation
    }
    
    int main()
    {
        cout.setf(ios::fixed, ios::floatfield);		//Fixed format
    
    	double p[2][101];	
    	double x[10];	
    	double y[10][10];	
    	double aa;
    
    	stringstream fileresults;
    
    	for(int n=4; n<=4; n=n+2)	//die schleife für die verschiedenen n-werte die man
    	{					//durchrechnen soll
    
    		fileresults.flush();
    
    		for(int a=0; a<=100; a++)	//die schleife für die punkte zum plotten
    		{
    			aa=a;				//"double aa wegen aa/10
    			p[0][a] = (aa/10)-5;	//x-wert fürs plotten
    
    			for(int b=0; b<=n; b++) //schleife für die stützpunkte FUNKTIONIERT!!!!!!
    			{
    				x[b]=(10.0000*b/n)-5;                     
    				y[0][b]=1.0000/(1+x[b]*x[b]);
    				//x[0][b]=5*cos((2*b+1)/(2*(nn+1))*PI);
    				//y[0][b]=1/(1+x[0][b]*x[0][b]);
    				//cout << "x ist " << x[b] <<endl;
    				//cout << "y ist " << y[0][b] <<endl;
    			}
    
    			for(int c=1; c<=n; c++)			//schleifen für das spaltenweise ausrechnen
    			{
    												//im neville-schema
    				for(int d=0; d<=n-c; d++)	//          ERSTER DURCHGANG IST RICHTIG, DANACH DANN FALSCH
    				{							
    					y[c][d]= interpolate(x[d], x[d+c], y[c-1][d], y[c-1][d+1], p[0][a]);
                        //cout<<y[c][d];
                        //cin.get();
    				}
                cout<<endl;
    			}
    			p[1][a]=y[n][0]; //y-wert fürs plotten
    
    			fileresults << p[0][a] << "		" << p[1][a]<< endl;
    		}
    
    		stringstream filename;
    		filename << "n=" << n << ".dat";
    
    		ofstream file;
    		file.open(filename.str().c_str(), ios::app);
    		file << fileresults.str();
    		file.close();
    
    		cout << "Das Ergebnis ist " << p[1][95] << endl;
            cin.get();
    	}
        return 0;
    }
    

    1. Zeile 28 soll eigentlich mein String gelöscht werden, also wenn es ein neues "n" gibt. Das Ergebnis, wenn ich das Programm durchlaufen lasse ist aber, dass in der Datei n=4 die richtigen Zahlen stehen, also einmal -5 bis 5 in 0.1er Schritten.
    In der Datei n=6 stehen aber die Ergebnisse von n=4 und n=6 usw bis in der Datei n=10.dat dann alle stehen. Kommt mir also so vor, als würde der String nicht gelöscht leider.

    2. Zeile 46-55.
    Hier berechnet er mir für c=1 die richtigen Werte, für ab c=2 sind die Werte falsch. Hab jetzt schon y[n][n] gesetzt, weil cih erst dachte es liegt daran, dass er probleme damit hat, weil cih die y immer überschrieben habe. aber die Werte sind noch immer nicht korrekt 😞

    So wie ich das sehe, macht er für y[2][0] folgende Rechnung für a=95:
    (4.5-x[0])*y[1][1]-(4.5-x[2])*y[1][0])/(x[2]-x[0])
    Das ist auch die korrekte Rechnung. die y[1][0] und y[1][1] sind auch richtig aber er gibt mir nicht den mit taschenrechner berechneten Wert aus. Woran liegt das?????? bin echt am verzweifeln 😞

    Wäre echt super super nett wenn mir das jemand sagen könnte.

    Bis hoffentlich bald, Till


  • Mod

    liebero3 schrieb:

    1. Zeile 28 soll eigentlich mein String gelöscht werden, also wenn es ein neues "n" gibt. Das Ergebnis, wenn ich das Programm durchlaufen lasse ist aber, dass in der Datei n=4 die richtigen Zahlen stehen, also einmal -5 bis 5 in 0.1er Schritten.
    In der Datei n=6 stehen aber die Ergebnisse von n=4 und n=6 usw bis in der Datei n=10.dat dann alle stehen. Kommt mir also so vor, als würde der String nicht gelöscht leider.

    flush() macht, dass alle Sachen die du in den Stream geschrieben hast, auch wirklich ankommen. Was in diesem Fall herzlich nutzlos ist, da du ja die Sachen die du in den Stream geschrieben hast, wieder rauslöschen willst. Dazu ist ignore() gut.

    Zu 2: Weiß nicht, habe gerade keine Muße, den Algorithmus nachzuvollziehen.


Anmelden zum Antworten