Namespaces
Variants

std::partial_sum

Von de.cppreference.net
 
 
Algorithmenbibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z. B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Batch-Operationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Reihenfolgeändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
 
Definiert in Header <numeric>
template< class InputIt, class OutputIt >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first );
(1) (constexpr seit C++20)
template< class InputIt, class OutputIt, class BinaryOp >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first, BinaryOp op );
(2) (constexpr seit C++20)
1) Wenn [firstlast) leer ist, tut nichts.
Andernfalls führt der Reihe nach die folgenden Operationen durch:
  1. Erzeugt einen Akkumulator acc, dessen Typ der Werttyp von InputIt ist, und initialisiert ihn mit *first.
  2. Weist acc *d_first zu.
  3. Für jede ganze Zahl i in [1std::distance(first, last)) führt der Reihe nach die folgenden Operationen durch:
a) Berechnet acc + *iter(bis C++20)std::move(acc) + *iter(seit C++20), wobei iter der nächste ite Iterator von first ist.
b) Weist das Ergebnis acc zu.
c) Weist acc[1] *dest zu, wobei dest der nächste ite Iterator von d_first ist.
2) Wie (1), berechnet jedoch stattdessen op(acc, *iter)(bis C++20)op(std::move(acc), *iter)(seit C++20).

Gegeben binary_op als die eigentliche binäre Operation:

  • Wenn eine der folgenden Bedingungen erfüllt ist, ist das Programm fehlerhaft (ill-formed):
  • Der Werttyp von InputIt ist nicht aus *first konstruierbar.
  • acc ist nicht beschreibbar in d_first.
  • Das Ergebnis von binary_op(acc, *iter)(bis C++20)binary_op(std::move(acc), *iter)(seit C++20) ist nicht implizit in den Werttyp von InputIt konvertierbar.
  • Gegeben d_last als der zurückzugebende Iterator, ist das Verhalten undefiniert, wenn eine der folgenden Bedingungen erfüllt ist:Ändert irgendein Element von
  • binary_op oder [firstlast).[d_firstd_last)Ungültigmacht
  • binary_op irgendeinen Iterator oder Teilbereich in [firstlast] oder [d_firstd_last].


  1. Der tatsächliche zuzuweisende Wert ist das Ergebnis der Zuweisung im vorherigen Schritt. Wir nehmen an, dass das Zuweisungsergebnis hier acc ist.

Parameter

first, last - das Paar von Iteratoren, das den Bereich der zu summierenden Elemente definiert
d_first - der Anfang des Zielbereichs; darf gleich first
seinop - binäres Operationsfunktionsobjekt, das angewendet wird.

Die Signatur der Funktion sollte wie folgt sein:

Ret fun(const Type1 &a, const Type2 &b);

Die Signatur muss nicht const & enthalten.
Der Typ Type1 muss so sein, dass ein Objekt vom Typ std::iterator_traits<InputIt>::value_type implizit in Type1 konvertiert werden kann. Der Typ Type2 muss so sein, dass ein Objekt vom Typ InputIt dereferenziert und dann implizit in Type2 konvertiert werden kann. Der Typ Ret muss so sein, dass ein Objekt vom Typ InputIt dereferenziert und ein Wert vom Typ Ret zugewiesen werden kann. ​

Typanforderungen
-
InputIt muss die Anforderungen von LegacyInputIterator erfüllen.
-
OutputIt muss die Anforderungen von LegacyOutputIterator erfüllen.

Rückgabewert

Iterator auf das Element nach dem zuletzt geschriebenen Element oder d_first, wenn [firstlast) leer ist.

Komplexität

Gegeben N als std::distance(first, last):

1) Genau N-1 Anwendungen von operator+.
2) Genau N-1 Anwendungen der binären Funktion op.

Mögliche Implementierung

partial_sum (1)
template<class InputIt, class OutputIt>
constexpr // since C++20
OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first)
{
    if (first == last)
        return d_first;
    
    typename std::iterator_traits<InputIt>::value_type sum = *first;
    *d_first = sum;
    
    while (++first != last)
    {
        sum = std::move(sum) + *first; // std::move since C++20
        *++d_first = sum;
    }
    
    return ++d_first;
    
    // or, since C++14:
    // return std::partial_sum(first, last, d_first, std::plus<>());
}
partial_sum (2)
template<class InputIt, class OutputIt, class BinaryOp>
constexpr // since C++20
OutputIt partial_sum(InputIt first, InputIt last, 
                     OutputIt d_first, BinaryOp op)
{
    if (first == last)
        return d_first;
    
    typename std::iterator_traits<InputIt>::value_type acc = *first;
    *d_first = acc;
    
    while (++first != last)
    {
        acc = op(std::move(acc), *first); // std::move since C++20
        *++d_first = acc;
    }
    
    return ++d_first;
}

Hinweise

acc wurde aufgrund der Lösung von LWG Issue 539 eingeführt. Der Grund für die Verwendung von acc anstatt die Ergebnisse direkt aufzusummieren (d. h. *(d_first + 2) = (*first + *(first + 1)) + *(first + 2);) ist, dass die Semantik des letzteren verwirrend ist, wenn die folgenden Typen nicht übereinstimmen:

  • der Werttyp von InputIt
  • die beschreibbaren Typen von OutputIt
  • die Typen der Parameter von operator+ oder op
  • der Rückgabetyp von operator+ oder op

acc dient als Zwischenobjekt zum Speichern und Bereitstellen der Werte für jeden Schritt der Berechnung:

  • sein Typ ist der Werttyp von InputIt
  • es wird in d_first
  • geschriebenoperator+ sein Wert wird an op
  • oder operator+ übergebenop
enum not_int { x = 1, y = 2 };

char i_array[4] = {100, 100, 100, 100};
not_int e_array[4] = {x, x, y, y};
int  o_array[4];

// OK: uses operator+(char, char) and assigns char values to int array
std::partial_sum(i_array, i_array + 4, o_array);

// Error: cannot assign not_int values to int array
std::partial_sum(e_array, e_array + 4, o_array);

// OK: performs conversions when needed
// 1. creates “acc” of type char (the value type)
// 2. the char arguments are used for long multiplication (char -> long)
// 3. the long product is assigned to “acc” (long -> char)
// 4. “acc” is assigned to an element of “o_array” (char -> int)
// 5. go back to step 2 to process the remaining elements in the input range
std::partial_sum(i_array, i_array + 4, o_array, std::multiplies<long>{});

Es speichert den Rückgabewert von

#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

int main()
{
    std::vector<int> v(10, 2); // v = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
    
    std::cout << "The first " << v.size() << " even numbers are: ";
    // write the result to the cout stream
    std::partial_sum(v.cbegin(), v.cend(), 
                     std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
    
    // write the result back to the vector v
    std::partial_sum(v.cbegin(), v.cend(),
                     v.begin(), std::multiplies<int>());
    
    std::cout << "The first " << v.size() << " powers of 2 are: ";
    for (int n : v)
        std::cout << n << ' ';
    std::cout << '\n';
}

Beispiel

The first 10 even numbers are: 2 4 6 8 10 12 14 16 18 20 
The first 10 powers of 2 are: 2 4 8 16 32 64 128 256 512 1024

Führen Sie diesen Code aus

Ausgabe:

Fehlerberichte Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet. DR Angewendet auf
Verhalten wie veröffentlicht Korrektes Verhalten opLWG 242 C++98
durfte keine Nebeneffekte haben es darf die beteiligten Bereiche nicht ändern LWG 539
C++98
die Typanforderungen, die für die Gültigkeit der Ergebnisauswertungen und Zuweisungen nötig sind, fehlten

hinzugefügt

adjacent_difference
berechnet die Differenzen zwischen benachbarten Elementen in einem Bereich
accumulate
summiert oder faltet einen Bereich von Elementen auf
inclusive_scan
(C++17)ähnlich wie std::partial_sum, schließt das i-te Eingabeelement in die i-te
Summe ein
exclusive_scan
(C++17)ähnlich wie std::partial_sum, schließt das i-te Eingabeelement von der i-ten
Summe aus
(Funktionstemplate)