Matrix in Funktion übergeben.



  • Martin Subovic schrieb:

    Bei deinem Beispiel sind die Zahlen in den Arrays nur beispiele?

    ja die zahlen sind willkürlich gewählt, trotzdem musst du bei übergabe von mehrdimensionalen arrays alle bis auf die letzte dimension in der parameterliste angeben.



  • Wade1234 schrieb:

    Martin Subovic schrieb:

    Bei deinem Beispiel sind die Zahlen in den Arrays nur beispiele?

    ja die zahlen sind willkürlich gewählt, trotzdem musst du bei übergabe von mehrdimensionalen arrays alle bis auf die letzte dimension in der parameterliste angeben.

    Das ist FALSCH!
    FALSCH!
    FALSCH!

    Du kannst die erste Dimension (vom Bezeichner aus gesehen) weglassen.

    Dann bist du aber immer noch in den anderen Dimension begrenzt.

    Das kannst du mit VLA umgehen.
    Als Parameter bei Funktion sind VLA genau richtig. (Wenn du variable Arrays brauchst)



  • ich dachte immer, variable arrays wären so unglaublich schlecht, nur was für deppen, ewig langsam, etc.? 🙄

    ja die erste dimension ist doch die ganz rechts und bei meinem lesestil dann eben die letzte. 😕


  • Mod

    Wade1234 schrieb:

    ich dachte immer, variable arrays wären so unglaublich schlecht, nur was für deppen, ewig langsam, etc.? 🙄

    Du musst verstehen, warum, dann verstehst du auch, warum die Art und Weise, wie VLAs hier meistens benutzt werden (so in dieser Art:

    puts("Wie viele Werte wollen Sie eingeben?");
    scanf("%i", anzahl_werte);
    double werte[anzahl_werte];
    

    ) der absolute Deppenschrott sind, der dem Programmierer die Kontrolle über seine eigenen Datenstrukturen entzieht, wohingegen das, was DirkB hier zeigt, das ist, wofür VLAs vorgesehen und perfekt geeignet sind.

    Von 'langsam' hat gewiss nie jemand etwas gesagt, der irgendeine Ahnung vom Thema hat.

    ja die erste dimension ist doch die ganz rechts und bei meinem lesestil dann eben die letzte. 😕

    Dann sprich lieber von 'innen' und 'außen'. Kommt es dir denn nicht konfus vor, wenn dein Verständnis von 'erste' die 'letzte' ist?



  • Wade1234 schrieb:

    ich dachte immer, variable arrays wären so unglaublich schlecht, nur was für deppen, ewig langsam, etc.? 🙄

    Es gibt das schon einen Unterschied, ob du die als Funktionsparamter nutzt oder das Array damit definierst.

    Wade1234 schrieb:

    ja die erste dimension ist doch die ganz rechts und bei meinem lesestil dann eben die letzte. 😕

    Um von Array[0][0] nach Array[1][0] zu kommen, musst der Compiler die Anzahl der Elemente beim rechten Indedx wissen.
    (Die Reihenfolge der Elemente im Speicher ist vom Standard vorgegeben)

    Ein 2D-Array ist ein Array von einem Array

    cdecl.org schrieb:

    char feld[5][3];

    declare feld as array 5 of array 3 of char

    https://cdecl.org/?q=char+feld%5B5%5D%5B3%5D%3B



  • Hier mal mein Code soweit. Er läuft aber spuckt immer die error Meldung aus.

    void nrerror(char error_text[])
    /* Numerical Recipes standard error handler */
    {
    	fprintf(stderr,"Numerical Recipes run-time error...\n");
    	fprintf(stderr,"%s\n",error_text);
    	fprintf(stderr,"...now exiting to system...\n");
    	exit(1);
    }
    
    float choldc(float **a, int n ,float p[])
    {
    	void nrerror(char error_text[]);
    	int i,j,k;
    	float sum;
    
    	for (i=1;i<=n;i++) {
    		for (j=i;j<=n;j++) {
    			for (sum=a[i][j],k=i-1;k>=1;k--) sum -= a[i][k]*a[j][k];
    			if (i == j) {
    				if (sum <= 0.0)
    					nrerror("choldc failed");
    				p[i]=sqrt(sum);
    			} else a[j][i]=sum/p[i];
    		}
    	}
    	return 1;
    }
    
    float cholsl(float **a, int n, float p[], float b[], float x[])
    {
    	int i,k;
    	float sum;
    
    	for (i=1;i<=n;i++) {
    		for (sum=b[i],k=i-1;k>=1;k--) sum -= a[i][k]*x[k];
    		x[i]=sum/p[i];
    	}
    	for (i=n;i>=1;i--) {
    		for (sum=x[i],k=i+1;k<=n;k++) sum -= a[k][i]*x[k];
    		x[i]=sum/p[i];
    	}
    	return 1;
    }
    
    int main() {
    
        int n = 4;
        float L;
        int *p;
        int zeile =4;
        int spalte =4;
        float a[zeile][spalte];
    
    a[1][1]=3;   a[1][2]= -2; a[1][3]=0;     a[1][4]=0;
    a[2][1]= -2; a[2][2]=3;   a[2][3]= 6;    a[2][4]=0;
    a[3][1]=0;   a[3][2]=6;   a[3][3]=3;     a[3][4]= -2;
    a[4][1]=0;   a[4][2]=0;   a[4][3]= -2;   a[4][4]=3;
    
        L = choldc(a, n, p);
        printf(" Untere Dreiecksmatrix L %\n ", L);
    
        return 0;
    
    }
    

    Okay da die matrix nicht positiv definit ist das klar.
    Für

    int main() {
    
        int n = 4;
        float L;
        int *p;
        int zeile =4;
        int spalte =4;
        float a[zeile][spalte];
    
    a[1][1]=1;   a[1][2]= -0.2; a[1][3]=0;     a[1][4]=0;
    a[2][1]= -0.2; a[2][2]=2;   a[2][3]= -0.3;    a[2][4]=0;
    a[3][1]=0;   a[3][2]= -0.3;   a[3][3]=3;     a[3][4]= -0.4;
    a[4][1]=0;   a[4][2]=0;   a[4][3]= -0.4;   a[4][4]=4;
    
        L = choldc(a, n, p);
        printf(" Untere Dreiecksmatrix L %\n ", L);
    
        return 0;
    

    Aber gibts auch die Fehlermeldung und diese matrix ist positiv definit



  • Martin Subovic schrieb:

    Hier mal mein Code soweit. Er läuft aber spuckt immer die error Meldung aus.

    Was unterscheidet diesen Code vom Eröffnungspost?
    Da sind noch alle Fehler drin.



  • Nichts da es ein copy paste Fehler war. Entschuldigung

    void nrerror(char error_text[])
    /* Numerical Recipes standard error handler */
    {
    	fprintf(stderr,"Numerical Recipes run-time error...\n");
    	fprintf(stderr,"%s\n",error_text);
    	fprintf(stderr,"...now exiting to system...\n");
    	exit(1);
    }
    
    float choldc(int n, float a[n][n],float p[n])
    {
    	void nrerror(char error_text[]);
    	int i,j,k;
    	float sum;
    
    	for (i=0;i<n;i++) {
    		for (j=i;j<=n;j++) {
    			for (sum=a[i][j],k=i-1;k>=1;k--) sum -= a[i][k]*a[j][k];
    			if (i == j) {
    				if (sum <= 0.0)
    					nrerror("choldc failed");
    				p[i]=sqrt(sum);
    			} else a[j][i]=sum/p[i];
    		}
    	}
    	return 1;
    }
    
    float cholsl(int n, float a[n][n], float p[n], float b[n], float x[n])
    {
    	int i,k;
    	float sum;
    
    	for (i=0;i<n;i++) {
    		for (sum=b[i],k=i-1;k>=1;k--) sum -= a[i][k]*x[k];
    		x[i]=sum/p[i];
    	}
    	for (i=n;i>=1;i--) {
    		for (sum=x[i],k=i+1;k<=n;k++) sum -= a[k][i]*x[k];
    		x[i]=sum/p[i];
    	}
    	return 1;
    }
    
    int main() {
    
        int n = 4;
        float L;
        float p[n];
        int zeile =4;
        int spalte =4;
        float a[zeile][spalte];
    
    a[1][1]=3;   a[1][2]= -2; a[1][3]=0;     a[1][4]=0;
    a[2][1]= -2; a[2][2]=3;   a[2][3]= 6;    a[2][4]=0;
    a[3][1]=0;   a[3][2]=6;   a[3][3]=3;     a[3][4]= -2;
    a[4][1]=0;   a[4][2]=0;   a[4][3]= -2;   a[4][4]=3;
    
        L = choldc(n, a, p);
        printf(" Untere Dreiecksmatrix L %f \n ", L);
    
        return 0;
    
    }
    


  • main ist immer noch falsch.

    Wenn du ein Array als feld[4] definierst, dann darf als Index (beim Zugriff) nie die 4 (oder ein größerer Wert) auftauchen.
    https://youtu.be/FFAbhi6xnCo?t=1m30s

    Diesen Fehler machst du auch in den Funktionen (Schleifengrenzen)

    Du kannst dir ja mal zum Debuggen die Elemente, die gerade bearbeitet werden, mit den Indizes ausgeben.
    Das geht mit printf (ist etwas Schreibarbeit) oder mit dem Debugger (dafür ist der da).



  • Also überall n-1 in den Funktionen
    sowie in der main choldc(n-1....)?
    oder verstehe ich dich da falsch?
    Wenn ich es so mache gibt er mir keine Fehler oder Warnungen an,
    aber er gibt es als Fehler (nicht positiv definit aus) was ja nicht stimmt



  • DirkB schrieb:

    https://youtu.be/FFAbhi6xnCo?t=1m30s

    😃 Bleibt nur noch die Frage nach deiner Lieblingsfarbe! 😃



  • Martin Subovic schrieb:

    Also überall n-1 in den Funktionen
    sowie in der main choldc(n-1....)?
    oder verstehe ich dich da falsch?

    Nein!
    n ist die Größe!! Beim Aufruf von choldc musst du natürlich n und nicht n-1 angeben. Die Indizes laufen von 0 bis n-1. Du scheinst aber Indizes von 1 bis n zu nutzen, was nicht richtig ist.

    Vergleiche:

    for (i=1;i<=n;i++)
    for (i = 0; i < n; i++)
    


  • Martin Subovic schrieb:

    Also überall n-1 in den Funktionen
    sowie in der main choldc(n-1....)?

    Nein

    Martin Subovic schrieb:

    oder verstehe ich dich da falsch?

    Ja.
    An die Funktion übergibst du die Anzahl der Elemente pro Zeile/Spalte (also n (bei dir 4))

    In den Schleifen darf der Index das n aber nicht erreichen, da du sonst auf falsche Elemente vom Array zugreifst.*

    for (i=0;i<n;i++) { // hier ist das in Ordnung
            for (j=i;j<=n;j++) {      // Bis wohin zählt diese Schleife?
    
    for (i=n;i>=1;i--) { //Über welchen Bereich zählt diese Schleife?
    

    Martin Subovic schrieb:

    Wenn ich es so mache gibt er mir keine Fehler oder Warnungen an,
    aber er gibt es als Fehler (nicht positiv definit aus) was ja nicht stimmt

    Dafür müsstest du ja mit den richtigen Werten rechnen * (und der Algorithmus muss auch richtig sein).
    Bis jetzt hast du ja gerade erstmal die Werte richtig in die Funktion rein bekommen (wenn main stimmt)



  • float choldc(int n, float a[n][n],float p[n])
    {
    	void nrerror(char error_text[]);
    	int i,j,k;
    	float sum;
    
    	for (i=0;i<n;i++) {
    		for (j=i;j<n;j++) {
    			for (sum=a[i][j],k=i-1;k>=1;k--) sum -= a[i][k]*a[j][k];
    			if (i == j) {
    				if (sum <= 0.0)
    					nrerror("choldc failed");
    				p[i]=sqrt(sum);
    			} else a[j][i]=sum/p[i];
    		}
    	}
    	return 1;
    }
    
    float cholsl(int n, float a[n][n], float p[n], float b[n], float x[n])
    {
    	int i,k;
    	float sum;
    
    	for (i=0;i<n;i++) {
    		for (sum=b[i],k=i-1;k>=1;k--) sum -= a[i][k]*x[k];
    		x[i]=sum/p[i];
    	}
    	for (i=n-1;i>=0;i--) {
    		for (sum=x[i],k=i+1;k<n;k++) sum -= a[k][i]*x[k];
    		x[i]=sum/p[i];
    	}
    	return 1;
    }
    
    int main() {
    
        int n = 4;
        float L;
        float p[n];
        int zeile =4;
        int spalte =4;
        float a[4][4]={{1, -0.2, 0, 0},
                       {-0.2, 2, -0.3, 0},
                       {0, -0.3, 3, -0.4},
                       {0, 0, -0.4, 4}};
    
        L = choldc(n, a, p);
        printf(" Untere Dreiecksmatrix L %f \n ", L);
    
        return 0;
    
    }
    

    Also ich habe jetzt

    for (i=0;i<n;i++) { // hier ist das in Ordnung 
    
    for (j=i;j<=n;j++) {      // Bis wohin zählt diese Schleife?	// bis j<n geändert
    
    for (i=n;i>=1;i--) { //Über welchen Bereich zählt diese Schleife? //geändert zu             (i=n-1;i>=0;i--)
    


  • Hast du die anderen Schleifen (Start-, Endwerte, Inkrement) auch gleich mal überprüft?



  • Ja ich habe soweit alles geändert dass es passen sollte in den Funktionen.

    float choldc(int n, float a[n][n],float p[n])
    {
    	void nrerror(char error_text[]);
    	int i,j,k;
    	float sum;
    
    	for (i=0;i<n;i++) {
    		for (j=i;j<n;j++) {
    			for (sum=a[i][j],k=i-1;k>=0;k--) sum -= a[i][k]*a[j][k];
    			if (i == j) {
    				if (sum <= 0.0)
    					nrerror("choldc failed");
    				p[i]=sqrt(sum);
    			} else a[j][i]=sum/p[i];
    		}
    	}
    	return 1;
    }
    
    float cholsl(int n, float a[n][n], float p[n], float b[n], float x[n])
    {
    	int i,k;
    	float sum;
    
    	for (i=0;i<n;i++) {
    		for (sum=b[i],k=i-1;k>=0;k--) sum -= a[i][k]*x[k];
    		x[i]=sum/p[i];
    	}
    	for (i=n-1;i>=0;i--) {
    		for (sum=x[i],k=i+1;k<n;k++) sum -= a[k][i]*x[k];
    		x[i]=sum/p[i];
    	}
    	return 1;
    }
    

    In cholsl hab ich for

    sum=b[i]...  k>=0
    

    anstatt k>=1 dann in der zweiten for schleife k<n .

    Irgendwas in der main passt aber noch nicht da immer noch nich positiv definit angegeben wird

    int main() {
    
        int n = 4;
        float L;
        float p[n];
        int zeile =4;
        int spalte =4;
        float a[4][4]={{1, -0.2, 0, 0},
                       {-0.2, 2, -0.3, 0},
                       {0, -0.3, 3, -0.4},
                       {0, 0, -0.4, 4}};
    
        L = choldc(n, a, p);
        printf(" Untere Dreiecksmatrix L %f \n ", L);
    
        return 0;
    
    }
    


  • Martin Subovic schrieb:

    Ja ich habe soweit alles geändert dass es passen sollte in den Funktionen.

    Dann spiel mal den allerersten Durchlauf per Hand durch

    Martin Subovic schrieb:

    for (i=0;i<n;i++) {
    		for (j=i;j<n;j++) {
    Hier ist i=0,j=i also auch 0
    			for (sum=a[i][j],k=i-1;k>=0;k--) Welchen Wert hat k?
    

    Oh? Warte, da war doch was:

    DirkB (in derersten Antwort) schrieb:

    ⚠ Die Indizes vom Array fangen immer bei 0 an.

    Von wegen

    Martin Subovic schrieb:

    Irgendwas in der main passt aber noch nicht da immer noch nich positiv definit angegeben wird



  • Stimmt, also k>=1 belassen? aber das passt auch nicht

    for (sum=a[i][j],k=i-1;k>=1;k--) sum -= a[i][k]*a[j][k];
    

    wie könnte man das jetzt besser machen? (k=0;k<=i;k++)

    gleiches problem bei der zweiten funktion erste for schleife

    Ansonsten dürfte es passen.

    wenn k=i-1 und k>=0 dann gibt es eine konflikt für i=0



  • Man könnte ja mal 1 Sekunde investieren und irgendeine Suchmaschine befragen:
    Ich habe z.B. gerade http://web.mit.edu/~mkgray/afs/UROP/choldc.c gefunden. Von 1991. Sieht man insbesondere an der Parameterübergabe. Aber der Algorithmus ist offenbar derselbe. Schau dir mal an, wie es dort gelöst wurde.



  • Ja der Algorithmus is sehr ähnlich bzw der selbe.
    Das scheint mit eingängig nun.

    Wie bring ich die aber vernünftig in die main bzw wie soll die main aussehen.
    Wenn ich also die Funktionen nehme:

    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    #include "parameters.h"
    
    void choldc( matrix,
    	     np,
    	     dp )
    
      /* Inputs */
    
         double matrix[NMAT][NMAT];
         long   np;
         double dp[NMAT];
    
    {
    
      /* Locals */
    
      long i,j,k;                         /* Dummy variables */
      double sum;                         /* Temp variable */
    
     /**********
     **       **
     ** Begin **
     **       **
     **********/
    
      for( i=0; i<np; i++ )
        {
          for( j=i; j<np; j++ )
    	{
    	  sum = matrix[i][j];
    	  k = i;
    	  while ( --k >= 0 )
    	    sum -= matrix[i][k] * matrix[j][k];
    	  if ( i==j )
    	    {
    	      if (sum <= 0.0)
    		{
    		  printf("Choldc Failed! Exiting...\n");
    		  exit(1);
    		}
    	      else
    		dp[i] = sqrt( sum );
    	    }
    	  else
    	    matrix[j][i] = sum / dp[i];
    	}
        }
    
    }
    
    #include <stdio.h>
    #include "parameters.h"
    
    void cholsl( matrix,
    	     np,
    	     dp,
    	     b,
    	     x)
    
      /* Inputs */
    
         double matrix[NMAT][NMAT];
         long   np;
         double dp[NMAT];
         double b[NMAT];
         double x[NMAT];
    
    {
    
      /* Locals */
    
      long i,k;                           /* Dummy variables */
      double sum;                         /* Temp variable */
    
     /**********
     **       **
     ** Begin **
     **       **
     **********/
    
      for( i=0; i<np; i++ )
        {
          sum = b[i];
          k = i;
          while ( --k >= 0 )
    	sum -= matrix[i][k] * x[k];
          x[i] = sum / dp[i];
        }
    
      for( i=np-1; i>=0; i-- )
        {
          sum = x[i];
          k = i;
          while ( ++k < np )
    	sum -= matrix[k][i] * x[k];
          x[i] = sum / dp[i];
        }
    
    }
    

    Dann probier ich die main

    int main() {
    void choldc( matrix,
    	     np,
    	     dp )
    void cholsl( matrix,
    	     np,
    	     dp,
    	     b,
    	     x)
    
        int np = 4;
        float L,T;
        float dp[n];
    
        float a[4][4]={{1, -0.2, 0, 0},
                       {-0.2, 2, -0.3, 0},
                       {0, -0.3, 3, -0.4},
                       {0, 0, -0.4, 4}};
        float b[4] = {4,-1,0,0}
    
        L = choldc(matrix, np, dp);
        printf(" Untere Dreiecksmatrix L %f \n ", L);
        T = cholsl(matrix,np,dp,b,x);
        printf(" Lösungsvektor T %f \n ", T);
    
        return 0;
    

    Hier habe ich Schwierigkeiten die Funktionen in der main anzuwenden und zu printen


Anmelden zum Antworten