Brauche Hilfe für folgende Übung



  • Ups, danke für den Tip!

    #include<iostream>
    using namespace std;
    
    int main()
    {
    int x=27;
    int k=0;
    
    if (x >= 0) 
    { 
    	i = 1;
        while (x >= 0) 
        {
            cout << x << endl;
            x*3+1; 
        }
    
    }
    

    so besser?



  • von der formatierung her ists schon sehr viel besser
    vom quelltext her leider nicht

    ist noch immer fast 0 und das noch nicht korrekt
    was soll die zeile: i = 1; ?

    while (x >= 0) 
        {
            cout << x << endl;
            x*3+1; 
        }
    

    was willst du hier machen?
    eine endlosschleife bauen, weil x nie ein anderer wert zugewiesen wird?

    bb



  • #include<iostream>
    using namespace std;
    
    int main()
    {
    int x=27;
    int k=0;
    
    if (x >= 0) 
    { 
    
        while (x >= 0) 
        {
            cout << x << endl;
            x*3+1; 
        }
    
    }
    

    Wie weise ich denn x etwas zu? Sodass es mir die Ergebnisse wie in der Aufgabenstellungt anzeigt?

    Ich dachte nämlich:

    x muss grösser als null sein, wenn dem ist dann soll x*3+1 angezeigt werden (so habe ich die Aufgabe zumindest verstanden) 😕



  • x=x*3+1;
    😞



  • ohmann schrieb:

    x=x*3+1;
    😞

    dir scheint es echt an den grundlagen zu fehlen...
    ich hab mir die aufgabe zwar nicht durchgelesen, aber du solltest bevor du sie löst, noch mal dein buch/deine mitschriften/... durchlesen - dann wirst du hoffentlich nen ansatz zu stande bringen, der mehr als 5 zeilen umfasst...

    dann wird dir auch jmd richtig helfen...

    bb



  • Aleph1 schrieb:

    x muss grösser als null sein, wenn dem ist dann soll x*3+1 angezeigt werden (so habe ich die Aufgabe zumindest verstanden) 😕

    Ich fürchte du hast die Aufgabe falsch verstanden.

    Für den Startwert der Zahlenfolge gilt er muss größer oder gleich 0 sein.

    Also: X0 >= 0

    Die Bildungsvorschrift für die restliche Zahlenfolge (X1, X2, X3, ...) lautet (vermutlich!):

    3 * X[t]k[/t] + 1 , falls X[t]k[/t] ungerade
    X[t]k+1[/t] = 
            X[t]k[/t]/2, falls X[t]k[/t] gerade
    

    Vermutlich deshalb, weil du oben

    x k+1 😞 3xk + 1 falls xk ungerade und xk*=*2 falls xk gerade).

    stehen hast. In meinen Augen macht das "=" da keinen Sinn. Wenn man allerdings stattdessen Xk/2 annimmt, dann stimmt die Aussage mit der Unabhängigkeit vom Startwert nicht mehr, da für X0 = 0 eine Nullfolge entsteht, ohne dass die Werte 4, 2, 1 auftauchen würden.

    Hast du dich da vertippt, oder steht die Zeile
    x k+1 😞 3xk + 1 falls xk ungerade und xk=2 falls xk gerade)
    wirklich genau so in der Aufgabenstellung?



  • Hallo Mitleid!

    Ja das steht da wirklich so.
    Also bin ich jetzt soweit:

    #include<iostream>
    using namespace std;
    
    int main()
    {
    int x=27;
    int k=0;
    
    if (x >= 0) 
    { 
        while (x >= 0) 
        {
            cout << x << endl;
            x=3*x+1; 
    
    		if (3%2==1)
    		{
     }
        }
    
    }
    

    Aber irgendwie scheint es noch immer nich richtig zu sein, kann mir einer bitte weiterhelfen?



  • Aleph1 schrieb:

    Ja das steht da wirklich so.

    Hm, dann würde ich mich nochmal erkundigen, was damit gemeint sein soll, denn das macht irgendwie keinen Sinn.

    Aleph1 schrieb:

    Aber irgendwie scheint es noch immer nich richtig zu sein, kann mir einer bitte weiterhelfen?

    Es können und wollen dir sicher ein paar Leute helfen. Werner Salomon juckt es wahrscheinlich schon in den Fingern. 😃 😃

    Aber, was du bisher gezeigt hast legt die Vermutung nahe, dass du dich weder mit C++ noch mit der Aufgabenstellung richtig befasst hast. Und es wäre fahrlässig dich dieser Denk- und Fleißaufgaben zu berauben, denn nur so kommt ein Lernprozess in Gang.

    Sieh dir die Sachen genauer an, mach dir klar was verlangt wird und stelle dann konkrete Fragen. 😉 Die Aufgabenstellung ist recht simpel.



  • Soweit bin ich nun liebe community!

    #include<iostream>
    using namespace std;
    
    int main()
    {
    int x=27;
    int k=0;
    
    if (x >= 0)
    {
    while(k<9)
    {
    cout << x << endl;
    x=3*x+1;
    
    if(k%2 != 0)
    {
    x=3*x+1;
    }
    }
    
    }
    

    Ich hab mir nun wirklich Mühe gegeben...ist es bis hierhin richtig?
    Wie sollte ich nun die Else-Abfrage konstruieren? Kann mir hier bitte einer helfen?



  • gucken wir erst noch mal die aufgabe durch und schauen, was dort so drin steht:

    Betrachtet folgende Bildungsvorschrift einer Zahlenfolge:
    x k+1 😞 3xk + 1 falls xk ungerade und xk=2 falls xk gerade).
    wobei x0 >= 0
    Unabhängig vom Startwert x0 nimmt die Folge nach endlich vielen Schritten periodisch die Werte (4; 2; 1) an. Beispiel:
    x0 = 5; x1 = 16; x2 = 8; x3 = 4 ; x4 = 2; x5 = 1; x6 = 4; x7 = 2; x8 = 1;....

    ok, erst mal fertig durchlesen...

    Programmiere mit Hilfe der while- und der if-Anweisungen ein Programm das die Folgenglieder dieser Folge zu einem festen x0 >= 0 berechnet und am Bildschirm ausgibt.

    -> wir haben offensichtlich ein x0 >= 0 gegeben. und sollen dann was damit machen

    1. Als Erstes deklariere zwei integer-Variablen x und k. In der Variablen x soll der aktuelle Wert xk und in k der Index von xk (Anzahl bereits ausgeführter Schritte) gespeichert werden.
      Initialisiere die beiden Variablen mit sinnvollen Werten, z.B. x0 = 27, k = 0.

    int k = 0; anfang -> index = 0
    int x = gegebener_anfangs_wert; ist klar, x0 sollte ja iwie gegeben sein...

    1. Überlege aus obigen Angaben zum Konvergenzverhalten der Folge eine Abbruchbedingung für die while-Schleife, so dass die periodischen Werte nur ein Mal berechnet werden.

    klingt eigtl rel. einfach, nehmen wir einfach nen array mit ner länge von 3 und speichern dort die letzten 3 zahlen - gibt 2 möglichkeiten, wie wir das tun - entweder, indem wir uns den anfang merken oder indem wir immer hin und her kopieren... ich werds mal mit dem anfang merken versuchen...

    1. Programmiere in der Schleife die Berechnung der Folgenkomponenten xk.

    ist klar, dass wir das tun wollen^^

    also:

    const int x0 = 27; //unser gegebener startwert hier als globale konstante, damit man ihn schnell ändern kann
    //von einlesen steht nix in der aufgabe, also machen wir uns auch nicht mehr arbeit, als wir müssen
    
    //wir bauen uns erst mal ne fkt, die nen array und den anfang übergeben bekommt und für uns checkt, ob wir abbrechen drüfen
    bool convert(int *last_values, int index);
    
    int main()
    {
      int k = 0;
      int x = x0;
    
      int last_values[3] = {}; //0-initialisiert
    
      while(!convert(last_values, k))
      {
        if(k%2 == 0) //2 teilbar
        {
          x = 3*x +1;
          k = k+1;
        }
        else
        {
          x = x/2;
          k = k+1;
        }
        //unser merker für das konvergenz-verhalten muss noch aktualisiert werden:
        last_values[k%3] = x;
      }
    }
    
    bool convert(int *last_values, int index)
    {
      int first = index%3,
        second = (index+1)%3,
        third = (index+2)%3;
    
      return (last_values[first] == 1) && (last_values[second] == 2) && (last_values[third] == 4);
    }
    

    und schon wären wir fertig...
    (also für den fall, dass hier keine fehler mehr drin wären^^)

    ich würd es allerdings noch ein wenig anders schreiben...

    const int starting = 27;
    
    bool convert(int* last_values, int index)
    {
      bool R = values[index%3] == 1;
      R &= values[++index%3] == 2;
      R &= values[++index%3] == 4;
    
      return R;
    }
    
    int main()
    {
      int k = 0;
      int x = starting;
    
      int last_values[3] = {};
    
      while(!convert(last_values, k))
      {
        if(k%2 == 0)
        {
          x *= 3;
          ++x;
        }
        else
        {
          x /= 2;
        }
        ++k;
    
        last_values[k%3] = x;
      }
    }
    

    heißt nicht unbedingt, dass es so schöner ist, aber ich finds so übersichtlicher^^

    ich hab zwar nicht mit absicht fehler reingemacht, aber das hat nix zu sagen ;o)

    bb



  • @unskilled
    Das geht doch sicher noch schöner, oder?

    Z.B. ohne dieses Array und die zusätzliche Funktion. Du willst doch Aleph1 nicht unnötig verwirren, was?

    Übrigens würde der Startwert x0=0 bei dir zu einer Endlosschleife führen. Da ist aber auch die Aufgabenstellung recht schlampig formuliert.



  • Diese Folge ist die sogenannte Collatz-Folge und endet nach heutigen Kenntnisstand immer mit einer 1. Zudem ist sie ein schönes Beispiel für die Anwendung des boost.iterator_adaptors wie folgender Code zeigt:

    #include <algorithm> // copy
    #include <iterator> // ostream_iterator
    #include <iostream>
    #include <boost/iterator/iterator_adaptor.hpp>
    
    template< typename T >
    class basic_collatz : public boost::iterator_adaptor< basic_collatz< T >, T, T, boost::forward_traversal_tag, const T >
    {
    public:
        explicit basic_collatz( const T& x )
            : iterator_adaptor( x )
        {}
        void increment()
        {
            if( base_reference() % 2 == 0 )
                base_reference() /= 2;
            else
                ++( base_reference() *= 3 );
        }
        T dereference() const { return base_reference(); }
    };
    typedef basic_collatz< int > Collatz;
    
    int main()
    {
        using namespace std;
        for( int x; cout << "> ", cin >> x && x > 0; )
        {
            copy( Collatz( x ), Collatz( 1 ), ostream_iterator< int >( cout << "Collatz-Folge: ", " " ) );
            cout << endl;
        }
        return 0;
    }
    

    Gruß
    Werner

    PS.: nein - dieser Beitrag war nicht für Aleph1 gedacht 😉


  • Mod

    Es ist auch gar nicht nötig, sich drei Folgemitglieder zu merken. Da das aktuelle Glied nur vom Vorgänger abhängt, reicht es, auf 1 zu prüfen, denn wenn man erstmal bei der 1 ist, kommt danach immer 4,2,1.



  • SeppJ schrieb:

    Es ist auch gar nicht nötig, sich drei Folgemitglieder zu merken. Da das aktuelle Glied nur vom Vorgänger abhängt, reicht es, auf 1 zu prüfen, denn wenn man erstmal bei der 1 ist, kommt danach immer 4,2,1.

    hmmm... richtig xD
    ok, hätte man auch von selbst drauf kommen können ;o)
    ich überleg gerade, ob ich wohl die ausrede mit der uhrzeit bringen kann... aber ich denke, ich geb einfach zu, dass ichs verkackt hab 😉

    bb



  • Werner Salomon schrieb:

    ...und endet nach heutigen Kenntnisstand immer mit einer 1. ...

    Man vermutet es endet immer mit der Folge 4,2,1. Der Beweis fehlt noch. Bei Fermat vermutete man zuerst auch - erst nachdem der Beweis nun da ist kann man sagen man weiß es tut immer so wie vermutet. Es sei denn man ist Anhänger von Popper ... 🙂

    Werner Salomon schrieb:

    Zudem ist sie ein schönes Beispiel für die Anwendung des boost.iterator_adaptors wie folgender Code zeigt:

    Nein ist es nicht und nein zeigt er nicht. 😃

    SeppJ schrieb:

    Da das aktuelle Glied nur vom Vorgänger abhängt, reicht es, auf 1 zu prüfen, denn wenn man erstmal bei der 1 ist, kommt danach immer 4,2,1.

    Wie oben bereits erwähnt musst du bei Prüfung auf 1 anschließend nochmal prüfen ob die 4 und die 2 bereits aufgetaucht sind und du es nicht z.B. mit einem Startwert von 1 oder 2 zu tun hattest. Die Folge 4,2,1 soll ja nur 1 Mal auftauchen. Prüfen auf 4 tut es bzw. prüfen auf 1 mit der Bedingung k>1.

    Nebenbei, so wie dieser Hausaufgabe-Thread abgelaufen ist, wage ich mal zu bezweifeln, dass das irgendjemandem geholfen hat. 😉



  • Mitleid schrieb:

    Nebenbei, so wie dieser Hausaufgabe-Thread abgelaufen ist, wage ich mal zu bezweifeln, dass das irgendjemandem geholfen hat. 😉

    Also ich denke, mein Code ist verständlich genug, um ihm zu helfen 😛
    Und wenn er(sie?^^) dann noch die Kommentare zur Abbruchbedingung(von SeppJ etc) liest, sollte er es auch allein hinbekommen, wenn er zumindest den Willen hat, was zu verstehen...

    bb



  • @unskilled
    Ich glaube ja es handelt sich bei Aleph1 weder um einen Er noch um eine Sie sondern um einen SpamBot. 😃

    Dennoch. Ob jemand, der noch nicht einmal eine Zuweisung hinbekommen hat deinen Code (Funktionen, Arrays, Zeiger) verstehen wird ist fraglich. Selbst wenn, hast du ihn nicht motiviert sich mit der Aufgabe auseinanderzusetzen, indem du die Lösung lieferst.

    Ich kann ja verstehen warum manche Verzweifelte hier, kurz vor Abgabeschluß, ihre Hausaufgabe einstellen. Dennoch tut man ihnen keinen Gefallen wenn man ihnen die Arbeit abnimmt.

    Möglicherweise bekommt Aleph1 jetzt die Punkte für die Aufgabe, gelernt hat er jedoch nichts.

    Und wenn dann noch falsche Behauptungen gepostet werden, oder Beiträge nach dem Motto "Seht her, was ich alles kann!", dann kostet das den Hilfesuchenden auch noch kostbare Zeit. Irgendwo muss man ja auch verantwortlich handeln.

    P.S.: Wenn hier allerdings einer schreibt er braucht c++ nur für diese eine Aufgabe und sonst nie mehr, oder wenn es an dieser Aufgabe hängt, ob ein ganzes Semester den Bach runter geht, dann hätte ich (etwas Langeweile vorausgesetzt) auch keine Probleme damit eine Lösung hinzuschreiben.



  • Ihr verwirrt mich alle:

    So ich habe es jetzt soweit:

    #include<iostream>
    using namespace std;
    
    int main()
    {
    int x=27;
    int k=0;
    
    if (x >= 0)
    {
    while(k<9)
    {
    cout << x << endl;
    x=3*x+1;
    
    if(k%2 != 0)
    {
    x=3*x+1;
    }
    else{
         x=x/2; 
    }
    k++;
    
    }
    }
    }
    
    }
    

    Ist das so in Ordnung?



  • Unabhängig vom Problem solltest du dringend an deiner Einrückung arbeiten. So wirst du schnell die Übersicht verlieren (wenn nicht schon geschehen 😉 )...



  • Diese Folge ist die sogenannte Collatz-Folge und endet nach heutigen Kenntnisstand immer mit einer 1.

    Kannst du bitte eine Quelle angeben, wo dein immer bewiesen ist. Ansonsten ist der Kenntnisstand: Wir wissen es nicht.

    Ausserdem wird es doch erst interessant, wenn man einige Probleme loesen kann. Z.b. welches n<10^8 generiert die laengste Sequenz? Kann diese Frage dein Iterator beantworten?


Anmelden zum Antworten