n-te Wurzel aus x ziehen



  • Hallo,

    Ich habe folgendes Problem:
    Ich will mittels der Allgemeinerung des Heron-Verfahrens:
    http://www.mathepedia.de/Heron-Verfahren.aspx
    solange bis die differenz von a1 - a0 kleiner ist als ein entsprechendes epsilon.

    Hier zunächst mal mein Code:

    #include <stdio.h>
    const double epsilon = 0.0005f;
    double temp, var, differenz;
    
    double hoch(double x, int n);
    
    double sqrtn(int x, int n){
      var = x;
      do{
        temp = x;
        x = (x + (var / hoch(x, n-1)))/2;
        differenz = x - temp;
      } while (differenz <= epsilon);
      return x;
    }
    
    double hoch(double x, int n){
      double temp;
      int i;
    
      temp = x;
      for(i = 1; i < n; i++){ 
      temp = temp * x;
      }
      return temp;
    }
    
    int main(void){
      printf("%lf\n" ,sqrtn(8, 3));
      return 0;
    }
    

    Das Programm soll die 3. Wurzel aus 8 ziehen (=2), klappt aber irgendwie nicht. Bei ausführung in der Konsole kommt kein ergebnis. Ich schätze er hat sich irgendwo in einer Endlosschleife verfangen.
    Kann jmd vielleicht mal drüber schauen und mir evtl. sagen wo die fehler stecken?

    Vielen Dank schon mal.



  • while (fabs(differenz) <= epsilon);
    


  • könnte man statt hoch(x, n-1) nicht einfach x nehmen?

    @edit achja x würd ich der funktion lieber als double übergeben...



  • volkard schrieb:

    while (fabs(differenz) <= epsilon);
    

    sollte man nicht lieber differenz = temp - x; machen und dann das fabs() weglassen?



  • _-- schrieb:

    volkard schrieb:

    while (fabs(differenz) <= epsilon);
    

    sollte man nicht lieber differenz = temp - x; machen und dann das fabs() weglassen?

    Nö, du weißt ja nicht, welches kleiner ist.

    Aber man sollte die Bedingung negieren 😉



  • _-- schrieb:

    könnte man statt hoch(x, n-1) nicht einfach x nehmen?

    uups... hätte den text lieber bis zum verallgemeinerungsteil lesen sollen 🤡



  • was ich vergessen hab zu sagen. Es sollen keine anderen Bibliotheken verwendet werden. Also alles selber coden.



  • hab meinen code mal bissl geändert.
    die 3. wurzel aus 8 rechnet er zumindest richtig. aber bei anderen wurzeln kommen irgendwie komische ergebnisse raus. Und vorallem keine Kommazahlen.
    die verwendete formel ist eine formel die ein kumpel auf einem arbeitsblatt von seiner uni hatte:
    ai+1 = ai - ((ain - x)/ (n*ain-1))

    #include <stdio.h>
    const double epsilon = 0.0000005f;
    double temp, var, differenz;
    
    double hoch(double x, int n);
    
    double sqrtn(int x, int n){
      var = x;
      do{
        temp = x;
        x = x - (hoch(x, n)-var)/(n*hoch(x, n-1));
        differenz = x - temp;
        if(differenz < 0){
          differenz = -differenz;
        }
        printf("test\n");
      } while (differenz >= epsilon);
      return x;
    }
    
    double hoch(double x, int n){
      double temp;
      int i;
    
      temp = x;
      for(i = 1; i < n; i++){ 
      temp = temp * x;
      }
      return temp;
    }
    
    int main(void){
      printf("%lf\n" ,sqrtn(12208, 3));
      return 0;
    }
    


  • dein x ist immernoch int...



  • Riedelinho schrieb:

    die verwendete formel ist eine formel die ein kumpel auf einem arbeitsblatt von seiner uni hatte:
    ai+1 = ai - ((ain - x)/ (n*ain-1))

    das ist aber ne andere als die verallgemeinerungs formel von deinem ersten link 😕



  • Michael E. schrieb:

    _-- schrieb:

    volkard schrieb:

    while (fabs(differenz) <= epsilon);
    

    sollte man nicht lieber differenz = temp - x; machen und dann das fabs() weglassen?

    Nö, du weißt ja nicht, welches kleiner ist.

    Doch, beim Newton mit x0=x weiß man ja, was passiert.
    Im ersten Schritt hüpft xn evtl (wenn x<1) nach rechts und ab dann hüpft die Folge nach links ad infinitum. Es winkt eine do-Schleife recht freundlich. Falls sie jemals nicht nach links hüpft, war entweder n==1 und ein Sofort-Treffer ist passiert, oder die Rechengenauigkeit ist erschöpft und man ist bei der Maschinengenauigkeit angekommen. Man muß kein unbefriedigendes epsilon wählen oder den Zyklus abwarten.
    Also fabs weglassen und epsilon weglassen ist der gute Weg.
    Nur weiß der Prof das nicht. Ist das einer, dem man es erklären kann? Oder lieber stillschweigend machen, was er erwartet?



  • Also hab meinen Code nochmal verändert:

    #include <stdio.h>
    const double epsilon = 0.0000005f;
    double temp, var, differenz;
    
    double hoch(double x, int n);
    
    double sqrtn(double x, int n){
      var = x;
      do{
        temp = x;
        x = x - ((hoch(x, n)-var)/(n*hoch(x, n-1)));
        differenz = x - temp;
        if(differenz < 0){
          differenz = -differenz;
        }
        printf("test\n");
      } while (differenz >= epsilon);
      return x;
    }
    
    double hoch(double x, int n){
      double temp;
      int i;
    
      temp = x;
      for(i = 1; i < n; i++){ 
      temp = temp * x;
      }
      return temp;
    }
    
    int main(void){
      printf("%lf\n" ,sqrtn(1321, 3));
      return 0;
    }
    

    soweit ich es probiert habe müsste es stimmen...
    jann es jemand mal mit anderen werten versuchen?



  • Riedelinho schrieb:

    jann es jemand mal mit anderen werten versuchen?

    Hier ein Auto-Tester, der 10000 Wertepaare testet.

    #include <stdio.h>
    const double epsilon = 0.0000005f;
    double temp, var, differenz;
    
    double hoch(double x, int n);
    
    double sqrtn(double x, int n)
    {
        var = x;
        do
        {
            temp = x;
            x = x - ((hoch(x, n)-var)/(n*hoch(x, n-1)));
            differenz = x - temp;
            if(differenz < 0)
            {
                differenz = -differenz;
            }
        }
        while (differenz >= epsilon);
        return x;
    }
    
    double hoch(double x, int n)
    {
        double temp;
        int i;
    
        temp = x;
        for(i = 1; i < n; i++)
        {
            temp = temp * x;
        }
        return temp;
    }
    
    int main(void)
    {
        double basis1,exponent,potenz,basis2;
        for(basis1=1; basis1<=1000; basis1++)
        {
            for(exponent=1; exponent<=10; exponent++)
            {
                potenz=pow(basis1,exponent);
                basis2=sqrtn(potenz,exponent);
                if(fabs(basis2-basis1)>0.001)
                {
                    printf("Fehler! sqrtn(%f,%f)!=%f (richtig: %f)\n",potenz,exponent,basis2,basis1);
                }
            }
            printf("                    \r%f%% done...\r",(basis1*10+exponent)/100);
        }
        return 0;
    }
    

    Kein Fehler.



  • wärs nicht schön wenn auch basen zwischen .0,1. und negative getestet würden?


Anmelden zum Antworten