Flag wert Ausgeben in do while Schleife



  • Hallo liebe Forum Member,
    Ich habe ein relativ leichtes Problem (denk ich mal) aber komm momentan überhaupt nicht darauf (kein Schlaf)
    Ich habe einen Code, Broyden Methode um nicht lineares Gleichungssystem zu lösen.
    Der Code compiliert auch wunderbar. Nun will ich aber Flag = 1 falls bei meiner do while Schleife

    while (U > 1e-10 && count < 50);
    

    Die beschränkung auf 50 nicht ausreicht und Flag = 0 wenn der Durchlauf erfolgreich ist.
    Leider stehe ich total auf dem Schlauch. Hat jemand eine Idee und kann mir helfen?
    Do while Schleife startet Zeile 40 und geht bis 100.

    Vielen Dank soweit.
    Horn

    #include <math.h>
    #include <stdlib.h>
    #include "vorrueckwaertsub.c"
    #include "lrmp.c"
    
     /*
     *  F Function
     *  n Dimension
     *  x Argument [n] (input/output)
     *  f F(x) [n] (input/output)
     *  W Negative inverse Jacob Approximation [n^2] (input/output)
     *
     *
     * Broyden:
     *   xnew = x + W f
     *   fnew = F(xnew)
     *   Wnew = W - (W fnew) (s^T W) / (s^T W (fnew - f)),
     * where
     *   s = xnew - x (= Wf)
     */
    void broyden_update(void (*F)(double*, double*), int n, double* x, double* f, double** W )
    {
        double* fnew = calloc(n, sizeof(double));
    
        int *p = calloc(n, sizeof(int));    
        double* xnew = calloc(n, sizeof(double));
        double* d = calloc(n, sizeof(double));
      /*  double** w = calloc(2, sizeof(double*));
            for (int i = 0; i < 2; i++) {
            w[i] = calloc(2, sizeof(double));
            }  */
    
     // double* stw = &fnew[n * 2];
     // double* wf1 = &fnew[n * 3];
        double denom, U;
    
        int i, j, count=0;
    
        do {
            if (count == 0) {
                F(x, f);
    	} else {
                   for(i=0; i<n;++i){
    		d[i]=-f[i];
                    }
    
    		Solve ( n,  W,  d,  p);
    
            	for (j = 0; j < n; ++j) {
    		        xnew[j] = x[j]+d[j];
    	        }
    
             	F(xnew, fnew);
    
            /*  for (j = 0, wij = W; j < n; ++j) {
            double sj = s[j];
    
            for (i = 0; i < n; ++i, ++wij)
                stw[i] += sj * wij[0];
             } */
    
    	         for (i = 0, denom = 0.0; i < n; ++i)
            	     denom += d[i] * d[i];
    
             /*for (j = 0, wij = W; j < n; ++j)
                wf1[j] += s[j] * fnew[j]; */
    
            	 for (j = 0; j < n; ++j) {
    			fnew[j] /= denom;
    	     		for (i = 0; i < n; ++i)
    		             	 W[i][j] += fnew[i] * d[j];
            		}
    
            for (i = 0; i < n; ++i)
                 x[i] = xnew[i];
    
           }
    
    	for (i = 0, U = 0.0; i < n; ++i)
                    U += d[i] * d[i];
    
    	U = sqrt(U);
    
            FILE *h = fopen("datei.txt", "w");
            if (!h) { /* FEHLER */ }
            fprintf(h, "     k      |       fx      |      ||x^k+1-x^k||       |       K-Ord     |   \n");
            fprintf(h, "--------------------------------------------------------------------------------\n");
            fprintf(h, " %d     |    %f   |      %f    |      %f      |      \n",  count, f[i], U, 0.5);
            fflush(h);
            fclose(h);
    
           // printf("  %d: %.3g\n", count, tol);
    
            count++;
        } while (U > 1e-10 && count < 50);
    }
    
    #include <math.h>
    #include <stdio.h>
    
    void F(double* x, double* f)
    {
        f[0]=((x[0])+3)*(pow(x[1], 3)-7.0)+18;
        f[1]=sin(x[1]*exp(x[0])-1);
    }
    
    int main()
    {
    
        //double c = 0.01;
        int n = 2;
        double x[2] = { -0.5,1.4};
        //double W[n][n];
    
        double* f= calloc(n, sizeof(double));
        double** W = calloc(2, sizeof(double*));
            for (int i = 0; i < 2; i++) {
            W[i] = calloc(2, sizeof(double));
            }	
    
       // int i;
    
        W[0][0]= pow(x[1], 3)-7;
        W[0][1]=(3*x[0]+3)*x[1];
        W[1][0]= x[1]* exp(x[0])*cos(x[1] *(exp(x[0])-1));
        W[1][1]= (exp(x[0])-1)*cos(x[1] *(exp(x[0])-1));
    
        broyden_update(F, n,  x, f,  W);
    
       /* for (i = 0; i < n * n; ++i)
            W[i] = 0.0;
        for (i = 0; i < n; ++i)
            W[i * n + i] = 1.0; */
    
        return 0;
    }
    


  • Du möchtest also in main feststellen, ob die Berechnung ok ist?

    Dazu nimmt man meist den Rückgabewert einer Funktion. Der darf dann natürlich nicht vom Typ void sein.

    Ein return !(count < 50) nach Zeile 100 reicht dann schon aus.

    In main musst du den Wert dann noch auswerten.



  • Vielen Dank, das hilft mir.

    Was meinst du mit auswerten in der main?
    Einfach printen? also etwas in der Form

    printf("Erfolgreicher Durchlauf bei 0: %d", !(count < 50));
    


  • ⚠ Vorweg:
    ⚠ Du hast ganz viel calloc aber kein free . -> Das gibt Speicherlecks.
    ⚠ Das sind grobe Fehler. Die musst du beheben.

    Hornschild schrieb:

    Was meinst du mit auswerten in der main?

    Dass main eine Info bekommt, dass die Schleife in broyden_update nicht ausgereicht hat,

    Hornschild schrieb:

    Einfach printen? also etwas in der Form

    printf("Erfolgreicher Durchlauf bei 0: %d", !(count < 50));
    

    1. ist count in main nicht bekannt, da es eine lokale Variable in broyden_update ist.
    1a. denk gar nicht erst über globale Variablen nach.

    2. ist !(count < 50) ein logischer Ausdruck. Der ergibt nur die Werte 0 oder 1.
    Also die Werte, die du Flag geben möchtest.

    Du musst dir also einen Weg ausdenken, wie du diese Information aus broyden_update nach main bekommst.
    (Tipp: wie bekommst du den Wert aus sgrt zurück oder die Speicheradresse bei callac ?)

    Du kannst auch einfach

    printf("Erfolgreicher Durchlauf bei 0: %d", count);
    

    in broyden_update machen.
    Solch eine Funktion sollte aber nicht mit dem Nutzer kommunizieren und du hattest auch nach Flag gefragt.



  • Ach ja, ich habe die free's vergessen danke.
    Könnte ich dazu dann etwa so vorgehen:

    int flag
    flag = broyden_update 
    if (flag = 0)
      printf(" Erfolgreicher Durchlauf bei 0: %d \n",flag);
    else
      printf("flag = 1 \n");
    


  • Hornschild schrieb:

    int flag
    flag = broyden_update  // dasz das syntaktisch falsch ist, ist klar, oder?
    if (flag = 0)  // das ist eine Zuweisung und immer false
      printf(" Erfolgreicher Durchlauf bei 0: %d \n",flag);
    else
      printf("flag = 1 \n");
    


  • Ja dagehört noch broyden_update(wert1,wert2,etc) rein.
    Ich weiß aber jetzt leider nicht weiter wie ich das sonst umsetzen soll.
    Geht das über die Zuweisung des Rückgabewerts?



  • Hornschild schrieb:

    Geht das über die Zuweisung des Rückgabewerts?

    Ja



  • Mh okay, leider scheitere ich hieran aber noch.
    Ich weise also flag = broyden_update (wert1,...) zu.
    Dann aber weiß ich nicht weiter wie ich dann auf flag =1 wenn es mehr als 50 count sind oder flag = 0 wenn es nicht abbricht komme.



  • Mit if und meiner ersten Antwort.



  • Ich steh auf dem Schlauch.
    Ich habe also den return Wert mit !count...
    Dann nehme ich flag = broyden_update(...)
    Jetzt komm ich aber nicht darauf wie ich die if bedingung gestalten muss.
    count ist ja eben eine lokale Variable und nutzt uns in der main nichts.
    Wie kann man die if Bedingung gestalten?



  • Hornschild schrieb:

    Jetzt komm ich aber nicht darauf wie ich die if bedingung gestalten muss.

    Hattest du doch schon (fast)

    if (flag == 0)  // Achtung hier ist ein ==
      printf("Erfolgreicher Durchlauf:\n");
    else
      printf("flag = 1 \n");
    

    Hornschild schrieb:

    count ist ja eben eine lokale Variable und nutzt uns in der main nichts.

    Dafür hast du ja den Rückgabewert, bzw. flag.

    Du kannst natürlich auch count zurückgeben. (Dann sollte main halt wissen, dass 50 die Abbruchbedingung ist)


Anmelden zum Antworten