std::reduce în C++

Ca accumulate, dar fără ordine fixă a operațiilor, ceea ce permite calcul în paralel.

Sintaxă
T reduce(InputIt first, InputIt last, T init);
T reduce(InputIt first, InputIt last, T init, BinaryOp op);
T reduce(ExecutionPolicy&& politica, ForwardIt first, ForwardIt last, T init);

Ce face std::reduce

std::reduce combină elementele ca std::accumulate, dar are voie să le grupeze și să le reordoneze. De aceea operația trebuie să fie asociativă și comutativă (adunare, înmulțire, minim, maxim), altfel rezultatul nu este garantat.

Avantajul apare cu o politică de execuție, de exemplu std::reduce(std::execution::par, ...) din <execution>, care împarte calculul pe mai multe nuclee. Atenție: biblioteca libc++ folosită de Apple clang nu oferă încă politicile paralele; ele funcționează cu GCC (cu biblioteca TBB) și MSVC. Fără init, valoarea de pornire este elementul implicit al tipului (0 pentru numere).

Parametri

Parametru Descriere
politica Opțional. std::execution::seq, par, par_unseq.
first, last Intervalul.
init Opțional. Valoarea de pornire.
op Opțional. Operație asociativă și comutativă.

Ce returnează

Rezultatul combinării.

Exemple

Exemplul 1: Suma unor încasări

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

int main() {
    std::vector<long long> incasari{1250, 980, 2310, 1755};

    std::println("Total: {} lei", std::reduce(incasari.begin(), incasari.end()));
    std::println("Total cu sold inițial: {} lei", std::reduce(incasari.begin(), incasari.end(), 5000LL));
}

Rezultat

Total: 6295 lei
Total cu sold inițial: 11295 lei

Exemplul 2: Maximul cu reduce

Maximul este asociativ și comutativ, deci se potrivește cu reduce. Scăderea nu se potrivește: (10 - 3) - 2 diferă de 10 - (3 - 2).

#include <algorithm>
#include <limits>
#include <numeric>
#include <print>
#include <vector>

int main() {
    std::vector<int> temperaturi{12, 18, 25, 21, 9};

    int maxim = std::reduce(temperaturi.begin(), temperaturi.end(), std::numeric_limits<int>::min(),
                            [](int a, int b) { return std::max(a, b); });
    std::println("Maxim: {}", maxim);
}

Rezultat

Maxim: 25

Greșeli frecvente

  • Folosești reduce cu o operație care nu este asociativă (scădere, împărțire, concatenare de texte): rezultatul poate diferi de la o implementare la alta.
  • Aduni numere cu virgulă mobilă și compari rezultatul exact cu cel de la accumulate: altă ordine a adunărilor poate schimba ultimele zecimale.

Comenzi înrudite

  • std::accumulate: Adună toate elementele unui interval pornind de la o valoare inițială (sau le combină cu o operație dată).
  • 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.