Quadratwurzel mit Heronverfahren



  • Hallo Leute 🙂

    ich muss Quadratwurzel in C++ ,ohne den
    Einsatz der Bibliotheksfunktion, ohne Selektion und ohne Iteration (d.h. ohne Schleifen, ohne
    Verzweigungen)in 8 Schritten programmieren. 😞
    In Aufgabe ist xn+1=(xn+a/xn)/2xn+1 = ( xn + a / xn ) / 2 als Hinweis gegeben. nn darf bei 8 abgebrochen werden.
    Meine Frage ist wie schätz man die xnxn richtig ab?
    Weil wenn ich zBsp die Wurzel aus 9,7 durch 2 (wobei der geschätzte Wert zwischen 3 und 4 liegt) dividiere bekomme ich viel größere Zahl als der geschätzte Wertebereich. Damit werden die restlichen Zahlen zu Groß oder zu klein.
    Wie kann man dieses Problem Lösen?



  • Ich glaube du verrechnest dich.

    Du hast eine Iterationsvorschrift gegeben. Nehmen wir mal als Beispiel deine 9:

    x_0=1 \\ x_1=(1+\frac{9}{1})/2 = 5 \\ x_2=(5+\frac{9}{5})/2 = 3,4 \\ x_3=(3,4+\frac{9}{3,4})/2 = 3,02 \\

    Du siehst, das Verfahren scheint zu funktionieren.

    Die Aufgabe scheint eher zu lauten, mach aus der iterativen Vorschrift eine Rekursion



  • Danke Schlangenmensch 🙂 . Ich versuche mein Programm umzuschreiben.Wenn was melde ich mich wieder 😉
    Noch ne Frage ist bei Rekursion eine if()erlaubt? die Aufgabenstellung ist so komisch gestellt im Praktikumsblatt.Es scheint so als will der Proff nicht mal das haben 😃



  • Irgendwie wirst du auf eine Abbruch Bedingungen prüfen müssen. Was genau dein Prof will kann ich nicht sagen. Da könnte ich vlt was zu sagen wenn ich die Aufgabenstellung im Wortlaut kennen würde.



  • Die genaue Aufgabenstellung :

    Schreiben Sie das Quadratwurzel Programm jetzt so, dass die Wurzelberechnung ohne den
    Einsatz der Bibliotheksfunktion, ohne Selektion und ohne Iteration (d.h. ohne Schleifen, ohne
    Verzweigungen) erfolgt. Die Quadratwurzel soll in einer Sequenz von acht aufeinander
    folgenden Rechenschritten ermittelt werden (siehe auch der Hinweis). Sie dürfen natürlich
    iostream für Ein- und Ausgabe verwenden.
    Hinweis:
    Die Quadratwurzel einer Zahl x lässt sich berechnen, indem sie als Grenzwert einer Folge
    gesehen wird: xn+1=(xn+a/xn)/2xn+1 = ( xn + a / xn ) / 2 mit beliebigem Anfangswert a ( z.B. a=x0a = x0 ).
    C++ Syntax z.B.: dWurzneu = ( dWurzalt + ( a / dWurzalt ) ) / 2.0;
    Für n = 0, 1, … konvergiert xn schnell gegen die Quadratwurzel von x.
    In Ihrem Programm können Sie bei n = 8 abbrechen und das Ergebnis ausgeben.
    Was bemerken Sie, wenn Sie die Quadratwurzel auf diese Art berechnen und weder
    Bibliotheksfunktion noch Selektions- oder Iterationsprimitiv einsetzen?



  • Ja, in der Aufgabenstellung ist if erlaubt, du musst ja gegen n prüfen. Dein Prof erwartet etwas so etwas als Lösung:

    double sqrt_recurse( double x, double a, unsigned int n )
    {
       if( n == 8 ) return x;
       else         return sqrt_recurse( ..., ..., n +1 );
    }
    
    double sqrt( double a )
    {
       return sqrt_recurse( ..., ..., 1 );
    }
    

  • Global Moderator

    Er will doch auch keine Verzweigung. Das klingt so, als wäre folgendes gesucht:

    double x0 = 1;
    double x1 = (x0 + a/x0) / 2;
    double x2 = ...;
    ...
    double x7 = (x6 + a/x6) / 2;
    cout << x7;
    

    Und was man bemerken soll? Vielleicht, dass man das auch arg viel kürzer und besser schreiben kann und der Prof einen mit dieser Aufgabe unnötig Arbeit macht.



  • 😮

    Will er wirklich eine so stumpfe Lösung haben?

    Warum wird erwähnt, dass man bei n = 8 abbrechen darf? Es muss also doch eine Zählvariable geben, wozu sonst der Hinweis?


  • Global Moderator

    DocShoe schrieb:

    😮

    Will er wirklich eine so stumpfe Lösung haben?

    Weiß ich nicht, aber zumindest verstehe ich die Aufgabe so. Wobei ich die Aufgabe sehr unklar formuliert finde. Ich weiß nicht, was der didaktische Sinn dahinter sein sollte, aber ich wüsste genauso wenig, was der didaktische Sinn sein sollte, eine Iteration rekursiv zu schreiben.

    Warum wird erwähnt, dass man bei n = 8 abbrechen darf? Es muss also doch eine Zählvariable geben, wozu sonst der Hinweis?

    In der Formel in der Aufgabenstellung gibt es ein n.



  • SeppJ schrieb:

    Weiß ich nicht, aber zumindest verstehe ich die Aufgabe so. Wobei ich die Aufgabe sehr unklar formuliert finde. Ich weiß nicht, was der didaktische Sinn dahinter sein sollte, aber ich wüsste genauso wenig, was der didaktische Sinn sein sollte, eine Iteration rekursiv zu schreiben.

    Eine Iteration rekursiv zu schreiben, oder umgekehrt, kann schon dem Verständiss von Rekursionen dienen.

    Aber wenn wir hier zu dritt (mit TE zu viert) rum raten, was gewünscht sein soll, spricht das nicht für den Aufgabensteller.

    Wobei, wenn man die Aufgabe wörtlich nimmt, kommt SeppJs Lösung wohl hin...



  • DocShoe schrieb:

    😮

    Will er wirklich eine so stumpfe Lösung haben?

    Warum wird erwähnt, dass man bei n = 8 abbrechen darf? Es muss also doch eine Zählvariable geben, wozu sonst der Hinweis?

    ja er möchte wirklich solche Lösung haben , es ist leider der schlimmste Proff aus unseren Fachbereich sturrer alter Wirtschaftsinformatiker, bei dem ist sogar using namespace std; verboten. 😞
    Es ist auch keine Funktion erlaubt .
    Es passt woll von SteppJ der Vorschlag am Meisten 🙂



  • Hier ist mein Programm

    #include <iostream>
    
    using namespace std;
    
    int main() {
    
        double a;
    
        cout << "Bitte geben Sie eine Fließkommazahl ein: ";
        cin >> a;
        double x0 = 1; 
        double x1 = (x0 + a/x0) / 2;
        cout  << x1 << endl;
        double x2 = x1;
        double x3 = (x2 + a/x2) /2;
        cout << x3 << endl;
        double x4 = x3;
        double x5 = (x4 + a/x4) /2;
        cout << x5 <<endl;
        double x6 = x5;
        double x7 = (x6 + a/x6) /2;
        cout << x7 << endl;
    
        return 0;
    }
    

    ist das ok so? 🙂



  • Nein, das sind ja nur 4 Durchgänge.



  • SG1 schrieb:

    Nein, das sind ja nur 4 Durchgänge.

    Wenn ich acht Schritte mache bekomme ich das als Ausgabe:

    Bitte geben Sie eine Fließkommazahl ein: 9.7
    5.35
    3.58154
    3.14494
    3.11463
    3.11448
    3.11448
    3.11448
    3.11448



  • aus ästhetischen Gründen würde ich hier allerdings ein Makro einsetzen:

    #define F(x,y) double x = (y + a/y) /2
    

    und dann schreiben

    F(x1,x0);   //statt: double x1 = (x0 + a/x0) / 2;
    [...]
    F(x7,x6);   //statt: double x7 = (x6 + a/x6) /2;
    

    Man könnte auch noch die cout << ..-Zeile ins Makro packen.



  • zufallswert schrieb:

    aus ästhetischen Gründen würde ich hier allerdings ein Makro einsetzen:

    #define F(x,y) double x = (y + a/y) /2
    

    und dann schreiben

    F(x1,x0);   //statt: double x1 = (x0 + a/x0) / 2;
    [...]
    F(x7,x6);   //statt: double x7 = (x6 + a/x6) /2;
    

    Man könnte auch noch die cout << ..-Zeile ins Makro packen.

    ich glaube , dass mein proff damit nicht einverstanden würde(näheres lese vorherige Posts). Habe define nur in headern gesehen in main noch nie 🙄
    Aber trotzdem Danke für den Hinweis 😋



  • oder so:

    #include <iostream>
    using namespace std;
    double F(double a, double x){ return (x + a/x)/2; }
    int main() {
        double a;
        cout << "Bitte geben Sie eine Fließkommazahl ein: ";
        cin >> a;
        cout << F(a, F(a, F(a, F(a, F(a, F(a, F(a, F(a, a)))))))) << endl;
    }
    


  • oder besser:

    cout << F(a, F(a, F(a, F(a, F(a, F(a, F(a, F(a, 1)))))))) << endl;
    


  • ... oder so ....

    #include <iostream>
    using namespace std;
    
    double F(double a, double x){ return (x + a/x)/2; }
    double F2(double a, double x){ return F(a, F(a, x)); }
    double F4(double a, double x){ return F2(a, F2(a, x)); }
    double F8(double a, double x){ return F4(a, F4(a, x)); }
    
    int main() {
        double a;
        cout << "Bitte geben Sie eine Fließkommazahl ein: ";
        cin >> a;
        cout << F8(a, 1) << endl;
    }
    

  • Global Moderator

    Proggerin schrieb:

    SG1 schrieb:

    Nein, das sind ja nur 4 Durchgänge.

    Wenn ich acht Schritte mache bekomme ich das als Ausgabe:

    Bitte geben Sie eine Fließkommazahl ein: 9.7
    5.35
    3.58154
    3.14494
    3.11463
    3.11448
    3.11448
    3.11448
    3.11448

    Deine Ausgabe hat nur 7 Stellen (ist die Standardeinstellung), der double wird aber genauer sein (so ca. 15 Stellen). Wenn du die precision erhöhst, sollte man das sehen können.



  • SeppJ schrieb:

    Proggerin schrieb:

    SG1 schrieb:

    Nein, das sind ja nur 4 Durchgänge.

    Wenn ich acht Schritte mache bekomme ich das als Ausgabe:

    Bitte geben Sie eine Fließkommazahl ein: 9.7
    5.35
    3.58154
    3.14494
    3.11463
    3.11448
    3.11448
    3.11448
    3.11448

    Deine Ausgabe hat nur 7 Stellen (ist die Standardeinstellung), der double wird aber genauer sein (so ca. 15 Stellen). Wenn du die precision erhöhst, sollte man das sehen können.

    PS: bin die Proggerin, habe mich registriert 🕶
    darf keine setter und getter benutzen . Geht es auch nicht mit float ?