std::accumulate în C++

Adună toate elementele unui interval pornind de la o valoare inițială (sau le combină cu o operație dată).

Sintaxă
T accumulate(InputIt first, InputIt last, T init);
T accumulate(InputIt first, InputIt last, T init, BinaryOp op);

Ce face std::accumulate

std::accumulate (din <numeric>) pornește de la init și adaugă, de la stânga la dreapta, fiecare element: init = init + element. Cu al patrulea argument poți folosi altă operație: înmulțire, concatenare, maxim.

Tipul rezultatului este tipul lui init, nu tipul elementelor. Dacă aduni numere cu zecimale pornind de la 0 (un int), zecimalele se pierd la fiecare pas. Pornește de la 0.0.

Din C++23 există și std::ranges::fold_left(v, init, op), echivalentul pentru ranges.

Parametri

Parametru Descriere
first, last Intervalul.
init Valoarea de pornire; îi dă și tipul rezultatului.
op Opțional. Funcție (acumulat, element) care returnează noul acumulat.

Ce returnează

Valoarea acumulată.

Exemple

Exemplul 1: Suma și media notelor

#include <numeric>
#include <print>
#include <vector>

int main() {
    std::vector<double> note{9.5, 8.0, 7.25, 10.0};

    double suma = std::accumulate(note.begin(), note.end(), 0.0);
    std::println("Suma: {:.2f}", suma);
    std::println("Media: {:.2f}", suma / note.size());
}

Rezultat

Suma: 34.75
Media: 8.69

Exemplul 2: Capcana lui 0 în loc de 0.0

Cu 0, rezultatul este int și fiecare sumă parțială este trunchiată: 0 + 1.5 = 1, 1 + 2.5 = 3, 3 + 3.5 = 6.

#include <numeric>
#include <print>
#include <vector>

int main() {
    std::vector<double> v{1.5, 2.5, 3.5};

    std::println("Cu 0:   {}", std::accumulate(v.begin(), v.end(), 0));
    std::println("Cu 0.0: {}", std::accumulate(v.begin(), v.end(), 0.0));
}

Rezultat

Cu 0:   6
Cu 0.0: 7.5

Exemplul 3: Produs, concatenare și fold_left

#include <algorithm>
#include <functional>
#include <numeric>
#include <print>
#include <string>
#include <vector>

int main() {
    std::vector<int> v{1, 2, 3, 4, 5};
    std::println("Produs: {}", std::accumulate(v.begin(), v.end(), 1, std::multiplies<>()));

    std::vector<std::string> cuvinte{"Ana", "are", "mere"};
    std::string fraza = std::accumulate(cuvinte.begin() + 1, cuvinte.end(), cuvinte[0],
                                        [](std::string a, const std::string& b) { return a + " " + b; });
    std::println("{}", fraza);

    std::println("fold_left: {}", std::ranges::fold_left(v, 0, std::plus<>()));
}

Rezultat

Produs: 120
Ana are mere
fold_left: 15

Greșeli frecvente

  • Inițializezi cu 0 o sumă de double și pierzi zecimalele.
  • Aduni mulți int mari pornind de la 0: suma depășește limita lui int. Pornește de la 0LL (long long).
  • Uiți #include <numeric>: accumulate nu este în <algorithm>.

Comenzi înrudite

  • std::reduce: Ca accumulate, dar fără ordine fixă a operațiilor, ceea ce permite calcul în paralel.
  • std::transform_reduce: Transformă fiecare element și combină rezultatele într-o singură valoare, într-o singură trecere.
  • std::partial_sum: Calculează sumele parțiale (cumulate): fiecare element al rezultatului este suma tuturor elementelor până la el.
  • std::count: Numără de câte ori apare o valoare (count) sau câte elemente îndeplinesc o condiție (count_if).