std::accumulate und Potenzreihe



  • Hallo ihr Lieben,

    ich überlege gerade, wie ich mittels std::accumulate eine Potenzreihe ausrechnen kann. Sagen wir ich habe gegeben

    S=i=0naiTiS = \sum_{i=0}^n \, a_i \, T^i

    Die Koeffizienten aia_i kann ich bequem in einem vector std::vector<double> coef speichern, d.h. ich könnte zu einem gegebenen T ansetzen

    double T; // irgendein Wert
    std::accumulate(coef.begin(), coef.end(), 0.0,
      [T](double sum, double a){ return sum + a * T; }
    

    Das Problem ist nun, dass T derart potentziert werden muss, je nachdem an welcher Stelle das Aufsummieren im Vektor coef gerade steht. Mit iterator - Arithmetik wäre die Potenz gerade iter - coef.begin() .

    Lässt sich das einbauen, also auf den verwendeten Iterator zugreifen?

    Oder gibt es ganz andere elegante Ansätze - ich sehe es gerade als Programmierübung. 🙂

    Gruß,
    -- Klaus.



  • Der Accululator ist einfach ein Paar aus Summe und Index, also <sum, index>.



  • knivil schrieb:

    Der Accululator ist einfach ein Paar aus Summe und Index, also <sum, index>.

    Meinst du damit std::pair ?

    Gruß,
    -- Klaus.



  • Folgender Funktor anstatt dem Lambda:

    class S_functor
    {
    public:
      // Konstruktor
    
      double operator()(double sum, double coef)
      {
         auto t = std::pow(base_t_, i_++);
         return sum + coef * t;
      }
    
    private:
      double base_t_;
      size_t i_ = 0;
    };
    


  • Klaus82 schrieb:

    Oder gibt es ganz andere elegante Ansätze - ich sehe es gerade als Programmierübung. 🙂

    Manche haben sowas wie integer-ranges oder -iteratoren. Damit und mit inner_product könnte es auch klappen.



  • so:

    double coef[] = { 1, -4, -5 };
        for( double x; cin >> x; )
            cout << "f(" << x << ") = " 
                << accumulate( begin(coef), end(coef), 0.0, [x]( double sum, double a_i )->double { return sum * x + a_i; } ) 
                << endl;
    

    oder?



  • Danke Werner, ich dachte schon keiner kennt hier das Horner-Schema.



  • Also ich bin es mal ohne std::accumulate mit einer for Schleife angegangen, vielleicht muss ich nicht immer mit Kanonen auf Spatzen schießen:

    // T gegeben
    
    double power_series = 0.0;
    
    for(unsigned int = 0; i < coef.size(); ++i)
      power_series += coef[ i ] * boost::units::pow<i>( T );
    

    Nur jetzt knirscht es bei Boost, dass i nicht konstant wäre? Muss ich aus dem i in jedem Durchlauf eine Konstante basteln?

    Gruß,
    -- Klaus.



  • boost::units::pow ist für Potenzierung zur Compiletime gedacht.
    Nimm std::pow für variable Potenzen.



  • Nathan schrieb:

    boost::units::pow ist für Potenzierung zur Compiletime gedacht.
    Nimm std::pow für variable Potenzen.

    Okay, verstehe. Ich dache ich könnte gleich die 'schnellere' Variante von boost nehmen.

    Gruß,
    -- Klaus.



  • Klaus82 schrieb:

    Nathan schrieb:

    boost::units::pow ist für Potenzierung zur Compiletime gedacht.
    Nimm std::pow für variable Potenzen.

    Okay, verstehe. Ich dache ich könnte gleich die 'schnellere' Variante von boost nehmen.

    Die ist nur schneller, wenn der Wert zur Compilezeit feststeht.
    Aus pow<2>(x) macht sie nämlich x*x und so für alle kleineren (?) Potenzen.
    Das geht aber nicht, wenn das eine Variable ist.



  • Klaus82 schrieb:

    Ich dache ich könnte gleich die 'schnellere' Variante von boost nehmen.

    Die wäre auch nicht schneller als das simple Horner Schema (s. 12:57:58) - eher im Gegenteil!


  • Mod

    Aus pow<2>(x) macht sie nämlich x*x und so für alle kleineren (?) Potenzen.

    Das geht mit TMP fuer alle Exponenten. Zumindest seit C++11.

    Horner-Schema ist hier aber ein Muss.



  • Arcoth schrieb:

    Aus pow<2>(x) macht sie nämlich x*x und so für alle kleineren (?) Potenzen.

    Das geht mit TMP fuer alle Exponenten. Zumindest seit C++11.

    Das ist mir klar, dass das mit allen geht.
    Ich hab mich nur gefragt, ob es eventuell bei pow<1000>(x) oder so, vielleicht effizienter wäre, das mit einer Schleife zu machen.



  • Nathan schrieb:

    Arcoth schrieb:

    Aus pow<2>(x) macht sie nämlich x*x und so für alle kleineren (?) Potenzen.

    Das geht mit TMP fuer alle Exponenten. Zumindest seit C++11.

    Das ist mir klar, dass das mit allen geht.
    Ich hab mich nur gefragt, ob es eventuell bei pow<1000>(x) oder so, vielleicht effizienter wäre, das mit einer Schleife zu machen.

    Na ja - bei einer Schleife wären es wahrscheinlich 999 Multiplikationen und wie ich die boost-people kenne, schafft es pow<1000>(x) mit ca. einem Dutzend Multiplikationen.


  • Mod

    Ich hab mich nur gefragt, ob es eventuell bei pow<1000>(x) oder so, vielleicht effizienter wäre, das mit einer Schleife zu machen.

    Auf gar keinen Fall. Square and Multiply wenden die an.



  • Arcoth schrieb:

    Ich hab mich nur gefragt, ob es eventuell bei pow<1000>(x) oder so, vielleicht effizienter wäre, das mit einer Schleife zu machen.

    Auf gar keinen Fall. Square and Multiply wenden die an.

    Auf gar keinen Fall! Für doubles nehmen die den ensprechenden Opcode.



  • Klaus82 schrieb:

    Also ich bin es mal ohne std::accumulate mit einer for Schleife angegangen, vielleicht muss ich nicht immer mit Kanonen auf Spatzen schießen:

    D.h. du hast das Beispiel von Werner nicht verstanden.


Anmelden zum Antworten