Reihe berechnen nur mit Arithmetik und Logik



  • Hallo

    ich habe ein Problem bei einer Aufgabe die ich in Informatik erledigen muss.

    Wir sollen eine Reihe berechnen und das nur durch Arithmetik und Logik einer While for schleife.

    Die Reihe die berechet werden soll:
    http://www.abload.de/img/reihe3oka.jpg

    Aufgaben stellung:
    Erstellen Sie je ein Schleifen-Programm zur Berechnung der Reihe. Hierzu verwenden Sie bitte nur die elementare Arithmetik und Logik, keine mathematischen Funktionen.

    Das Endkriterium für Programm 1 ist die Anzahl der Schleifendurchläufe. Hierzu wählen sie n 530947. Zum Nachweis der Korektheit zeigen Se das Ergebnis der ersten drei Teilsummen und das Ergebnis für n.

    Ich würde mich sehr über Hilfe freuen.

    LG Koebbe


  • Mod

    Koebbe schrieb:

    Ich würde mich sehr über Hilfe freuen.

    Ich helfe dir mal, Hilfe zu finden:
    Du brauchst Hilfe?
    Warum dir keiner helfen will.



  • Was er damit sagen will ist, dass wohl keiner deine Hausaufgaben erledigen wird. Allerdings werden wir dir gerne bei Problemen helfen, wenn du Fragen zu deinem bisher erarbeiteten Code hast.


  • Mod

    Es soll ja keiner behaupten, dass ich nie helfen würde:

    #include<iostream>
    #include<numeric>
    
    class Addend
    {
    private:
      unsigned int n;
    public:
      Addend(unsigned int n):n(n){}
      double operator*()
      {
        return 1./((2*n+1)*(2*n+1));
      }
      Addend& operator++()
      {
        ++n;
        return *this;
      }
      friend bool operator!=(Addend lhs, Addend rhs);
    };
    
    bool operator!=(Addend lhs, Addend rhs)
    {
      return lhs.n != rhs.n;
    }
    
    const unsigned max_n = 530947;
    
    int main()
    {
      std::cout << "Von n=0 bis n=" << max_n << ": " << std::accumulate(Addend(0), Addend(max_n + 1), 0.) << std::endl;
    }
    


  • Ne es soll auch keiner den Kompletten Code für mich machen.

    Nur ich habe derzeit das Problem das ich nicht den Richtigen ausdruck für
    meine Schleife finde.
    for(m= 0; m <= n; m++)
    s = 1/(2*m+1)*(2m+1);
    das habe ich gemacht aber damit habe ich nicht annähernd das gewünschte ergebniss



  • Du benutzt Ganzzahlarithmetik (-> Google). Mach aus der 1 ne 1.0.


  • Mod

    Und du berechnest ein Produkt anstatt einer Summe. Benutz mal +=.



  • SeppJ schrieb:

    Es soll ja keiner behaupten, dass ich nie helfen würde:

    ... std::accumulate(Addend(0), ...
    

    Ich weiß gar nicht wie das im Standard geregelt ist, aber im DEBUG braucht z.B. der vc für accumulate die typedefs wie iterator_category usw. Für eigene Iteratoren, die ich mit der STL benutzen möchte definiere ich mir die aus Gründen der Portablilität daher immer mit. Ich glaube dafür gibt es auch eine boost::iterator_facade oder so ähnlich.


  • Mod

    brotbernd schrieb:

    SeppJ schrieb:

    Es soll ja keiner behaupten, dass ich nie helfen würde:

    ... std::accumulate(Addend(0), ...
    

    Ich weiß gar nicht wie das im Standard geregelt ist, aber im DEBUG braucht z.B. der vc für accumulate die typedefs wie iterator_category usw. Für eigene Iteratoren, die ich mit der STL benutzen möchte definiere ich mir die aus Gründen der Portablilität daher immer mit. Ich glaube dafür gibt es auch eine boost::iterator_facade oder so ähnlich.

    Ahh, das erklärt die ganzen Fehlermeldungen als ich versucht habe, die partial_sums zu berechnen. War mir gar nicht bewusst, dass dies für Iteratoren zum Pflichtprogramm gehört und war ganz erstaunt, als es ohne nicht ging.

    Werde ich gleich mal ausbessern.



  • Das kann er aber so noch nicht abgeben, weil nicht die ersten drei Zwischensummen und dann das Endergebnis ausgegeben werden. Außerdem ist endl nicht so hübsch, wenn nur '\n' gemeint ist.
    Und Freunde sehen viel freundlicher aus, wenn sie in der Klasse definiert werden, gell?

    #include<iostream>
    #include<numeric>
    
    class Addend
    {
    private:
        unsigned n;
    public:
        Addend(unsigned n):n(n) {}
        double operator*()
        {
            return 1./((2*n+1)*(2*n+1));
        }
        Addend operator++()
        {
            ++n;
            return *this;
        }
        friend bool operator!=(Addend lhs, Addend rhs)
        {
            return lhs.n != rhs.n;
        }
    };
    
    const unsigned max_n = 530947;
    
    int main()
    {
        std::cout.precision(10);
        std::cout << std::accumulate(Addend(0), Addend(1), 0.) << '\n';
        std::cout << std::accumulate(Addend(0), Addend(2), 0.) << '\n';
        std::cout << std::accumulate(Addend(0), Addend(3), 0.) << '\n';
        std::cout << std::accumulate(Addend(0), Addend(max_n + 1), 0.) << '\n';
    }
    

  • Mod

    So, mit volkards und brotbernds Anmerkungen hier eine neue Version. Sie ist abgehärtet gegen alle Eventualitäten einer STL-Implementierung und hat ein bisschen besseren Stil. Bezüglich der Partialsummen: Es ist doch nicht nötig, dreimal das gleiche zu rechnen, wenn die STL eine Lösung bietet. Wir haben hier ja keine Rechenzeit zu verschenken.

    #include<iostream>
    #include<numeric>
    #include<iterator>
    #include<algorithm>
    #include<vector>
    
    class Addend: public std::iterator<std::input_iterator_tag, double>
    {
    private:
      unsigned int n;
    public:
      Addend(unsigned int n=0):n(n){}
      double operator*()
      {
        return 1./((2*n+1)*(2*n+1));
      }
      Addend& operator++()
      {
        ++n;
        return *this;
      }
      Addend operator++(int)
      {
        Addend old(*this);
        ++n;
        return old;
      }
      friend bool operator!=(Addend lhs, Addend rhs)
      {
        return lhs.n != rhs.n;
      }
      friend bool operator==(Addend lhs, Addend rhs)
      {
        return lhs.n == rhs.n;
      }
    };
    
    const unsigned max_part = 3;
    const unsigned max_n = 530947;
    
    int main()
    {
      std::vector<double> partial_sums(max_part);
      std::partial_sum(Addend(0), Addend(max_part), partial_sums.begin());
      std::ostream_iterator<double> double_out(std::cout, "\n");
      std::cout << "Die ersten " << max_part <<" Teilsummen:\n";
      std::copy(partial_sums.begin(), partial_sums.end(), double_out);
      std::cout << "Summe von n=0 bis n=" << max_n << ": " << std::accumulate(Addend(0), Addend(max_n + 1), 0.) << std::endl;
    }
    

    So kann man es abgeben. Absolut glaubwürdig als eigenes Werk.

    Ich frage mich, ob man noch ein paar typedefs einführen sollte. Das Wort double kommt für meinen Geschmack recht häufig vor, was wenn man später mal genaueres möchte?
    Außerdem könnte man noch eine Ausgabeklasse schreiben, welche die ersten n Teilsummen und die Summe bis m berechnet und ausgibt. Die main ist jetzt nämlich ein bisschen unaufgeräumt.



  • 😃 hört sich erstmal alles ganz nett an.

    Nur haben wir bis jetzt noch nicht mit

    #include <iostream>
    #include<numeric>
    #include<iterator>
    #include<algorithm>
    #include<vector>
    gearbeitet

    normal machen wir alles mit
    #include <stdio.h>



  • SeppJ schrieb:

    Ich frage mich, ob man noch ein paar typedefs einführen sollte. Das Wort double kommt für meinen Geschmack recht häufig vor, was wenn man später mal genaueres möchte?

    Jo, ich schlage mal vor, die wichtige Funktion per Template-Parameter mit den Typen zu versorgen.

    #include<iostream>
    #include<numeric>
    #include<iterator>
    #include<algorithm>
    #include<vector>
    
    template<typename numtype,typename counttype>
    class Addend: public std::iterator<std::input_iterator_tag, double>
    {
    private:
        counttype n;
    public:
        Addend(counttype n=0):n(n) {}
        numtype operator*()
        {
            return numtype(1)/numtype((2*n+1)*(2*n+1));
        }
        Addend& operator++()
        {
            ++n;
            return *this;
        }
        Addend operator++(int)
        {
            Addend old(*this);
            ++n;
            return old;
        }
        friend bool operator!=(Addend lhs, Addend rhs)
        {
            return lhs.n != rhs.n;
        }
        friend bool operator==(Addend lhs, Addend rhs)
        {
            return lhs.n == rhs.n;
        }
    };
    
    template<typename numtype,typename counttype>
    void solve(counttype max_part=3,counttype max_n=530947)
    {
        typedef Addend<numtype,counttype> Ad;
        std::vector<numtype> partial_sums(max_part);
        std::partial_sum(Ad(), Ad(max_part), partial_sums.begin());
        std::ostream_iterator<numtype> double_out(std::cout, "\n");
        std::cout << "Die ersten " << max_part <<" Teilsummen:\n";
        std::copy(partial_sums.begin(), partial_sums.end(), double_out);
        std::cout << "Summe von n=0 bis n=" << max_n << ": " << std::accumulate(Ad(), Ad(max_n + 1), numtype(0)) << std::endl;
    }
    
    int main()
    {
        solve<double,unsigned int>();
    }
    


  • Koebbe schrieb:

    normal machen wir alles mit
    #include <stdio.h>

    Also lernt ihr C und nicht C++?



  • Koebbe schrieb:

    😃 hört sich erstmal alles ganz nett an.

    Nur haben wir bis jetzt noch nicht mit

    #include <iostream>
    #include<numeric>
    #include<iterator>
    #include<algorithm>
    #include<vector>
    gearbeitet

    normal machen wir alles mit
    #include <stdio.h>

    Bist du sicher, dass du eine C++ und keine C Vorlesung besuchst?



  • SeppJ schrieb:

    So, mit volkards und brotbernds Anmerkungen hier eine neue Version.

    Wenn du das Ergebnis von partial_sum nicht für das anschließende accumulate, benutzt, kannst du doch für partial_sum gleich deinen double_out benutzen.

    template<typename numtype,typename counttype>
    void solve(counttype max_part=3,counttype max_n=530947)
    {
        typedef Addend<numtype,counttype> Ad;
        std::ostream_iterator<numtype> double_out(std::cout, "\n");
        std::cout << "Die ersten " << max_part <<" Teilsummen:\n";
        std::partial_sum(Ad(), Ad(max_part), double_out);
        std::cout << "Summe von n=0 bis n=" << max_n << ": " << std::accumulate(Ad(), Ad(max_n + 1), numtype(0)) << std::endl;
    }
    

  • Mod

    Schöne Verbesserungen 👍 . Eine habe ich auch noch:
    Der Operator++(int) sollte besser so aussehen:

    Addend operator++(int)
      {
        Addend old(*this);
        ++(*this);
        return old;
      }
    

    Dann ist das robust gegen Änderungen an der Inkrementierungsfunktionalität der Klasse.



  • Hmm ne jetzt bin ich mir grade nicht sicher. Bin leider nicht der Fitteste im Programmieren. Habe grade noch einmal geschaut, aber wie ihr es euch denken könnt es ist C 😞

    Da kann ich auch verstehen warum eure Programme anders sind



  • Da hat sich ja schon wieder ein std::endl eingeschlichen. 😮



  • Koebbe schrieb:

    Hmm ne jetzt bin ich mir grade nicht sicher. Bin leider nicht der Fitteste im Programmieren. Habe grade noch einmal geschaut, aber wie ihr es euch denken könnt es ist C 😞

    Dann stell die Frage nochmal im C-Forum. Und schreib dazu, was Du schon hast. Je mehr Du schon hast, desto hilfreicher werden die Antworten.


Anmelden zum Antworten