Biblioteca estándar de C++<numeric>
En el desarrollo diario de C++, a menudo nos encontramos con los siguientes requisitos:
- Calcular la suma total / producto acumulado de un array
- Calcular la suma de prefijos para consultas por intervalos
- Acumular por lotes para generar nuevas secuencias
- Calcular el producto interno (producto punto) entre vectores
Si todavía estás escribiendo a manoforbucles, entonces<numeric>es precisamente la herramienta de biblioteca estándar que deberías dominar.
En la biblioteca estándar de C++,<numeric>el archivo de cabecera proporciona un conjunto de plantillas de funciones para cálculos numéricos. Estas funciones pueden realizar varias operaciones numéricas sobre los elementos de un contenedor, como suma, producto, mínimo, máximo, etc. Estas plantillas de funciones son muy potentes y pueden aplicarse a cualquier tipo de contenedor, incluyendo arrays, vectores, listas, etc.
Antes de usar<numeric>las funciones del archivo de cabecera, necesitas incluir este archivo de cabecera en tu programa de C++:
#include <numeric>
Funciones comunes
<numeric>es el encargado en C++del cálculo de secuencias numéricasel archivo de cabecera central, centrado en operaciones de reducción, acumulación, diferencias, etc., y compatible con todos los contenedores STL;- Funciones básicas (
accumulate/partial_sum/iota) son el núcleo de C++98/11 y satisfacen la gran mayoría de las necesidades de cálculo numérico convencional; - C++17 añadió
reduce/inclusive_scanfunciones paralelas, etc., que pueden mejorar significativamente la eficiencia de cálculo con grandes volúmenes de datos, y deben usarse con estrategias de ejecución paralela.
| Nombre de función | Versión de C++ | Función principal | Prototipo de función simplificado (tomandovector<int>como ejemplo) |
Casos de uso típicos |
|---|---|---|---|---|
accumulate |
C++98 | Calcular la suma acumulada de una secuencia (operación binaria personalizable) | int accumulate(iterator beg, iterator end, int init); |
Calcular la suma total de un array, estadísticas de valores acumulados |
inner_product |
C++98 | Calcular el producto interno de dos secuencias (multiplicar los elementos correspondientes y luego acumular, con operación personalizable) | int inner_product(iter1 b1, iter1 e1, iter2 b2, int init); |
Producto punto de vectores, suma ponderada |
partial_sum |
C++98 | Calcular la suma de prefijos de una secuencia (el n-ésimo resultado = la suma de los primeros n elementos, operación personalizable) | void partial_sum(iter b, iter e, iter res); |
Generar array de sumas de prefijos, estadísticas acumulativas |
adjacent_difference |
C++98 | Calcular la diferencia entre elementos adyacentes de una secuencia (el n-ésimo resultado = elem[n] - elem[n-1], operación personalizable) | void adjacent_difference(iter b, iter e, iter res); |
Calcular diferencias, detectar cambios en una secuencia |
iota |
C++11 | Rellenar una secuencia con valores incrementales consecutivos (comenzando desde init, incrementando de uno en uno) | void iota(iter b, iter e, T init); |
Generar secuencias de enteros consecutivos, inicializar contenedores ordenados |
reduce |
C++17 | Acumulación en versión paralela (similar a accumulate, admite ejecución paralela, reducción sin orden) | T reduce(iter b, iter e, T init = T{}); |
Suma paralela de grandes volúmenes de datos, mejora la eficiencia de cálculo |
transform_reduce |
C++17 | Transformación + reducción (transformar primero los elementos, luego acumular, admite paralelismo) | T transform_reduce(iter1 b1, iter1 e1, iter2 b2, T init); |
Calcular producto interno en paralelo, sumar después de transformar |
inclusive_scan |
C++17 | Suma de prefijos en versión paralela (incluye el elemento actual, similar a partial_sum, admite paralelismo) | void inclusive_scan(iter b, iter e, iter res); |
Generar en paralelo un array de sumas de prefijos |
exclusive_scan |
C++17 | Suma de prefijos en versión paralela (sin incluir el elemento actual, el n-ésimo resultado = la suma de los primeros n-1 elementos) | void exclusive_scan(iter b, iter e, iter res, T init); |
Generar en paralelo una suma de prefijos 'que no incluye el propio elemento' |
1. accumulate
accumulateLa función se utiliza para calcular la suma de todos los elementos de un contenedor. Acepta tres parámetros: el iterador inicial del contenedor, el iterador final y el valor inicial.
Sintaxis:
template <InputIterator Iter, class T> T accumulate(Iter first, Iter last, T init);
Ejemplo:
Ejemplo
#include <numeric>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
int sum = std::accumulate(v.begin(), v.end(), 0);
std::cout << "Sum: " << sum << std::endl; // Salida: Sum: 15
return 0;
}
2. inner_product
inner_productLa función se utiliza para calcular la suma de los productos de los elementos correspondientes de dos contenedores.
Sintaxis:
template <InputIterator1 Iter1, InputIterator2 Iter2, class T> T inner_product(Iter1 first1, Iter1 last1, Iter2 first2, T init);
Ejemplo:
Ejemplo
#include <numeric>
#include <vector>
int main() {
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = {4, 5, 6};
int product_sum = std::inner_product(v1.begin(), v1.end(), v2.begin(), 0);
std::cout << "Product Sum: " << product_sum << std::endl; // Salida: Product Sum: 32
return 0;
}
3. partial_sum
partial_sumLa función se utiliza para calcular las sumas parciales de los elementos de un contenedor y almacenar los resultados en otro contenedor.
Sintaxis:
template <InputIterator InIter, OutputIterator OutIter> OutIter partial_sum(InIter first, InIter last, OutIter result);
Ejemplo:
Ejemplo
#include <numeric>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4};
std::vector<int> result(v.size());
std::partial_sum(v.begin(), v.end(), result.begin());
for (int i : result) {
std::cout << i << " "; // Salida: 1 3 6 10
}
return 0;
}
4. adjacent_difference
adjacent_differenceLa función se utiliza para calcular las diferencias entre elementos adyacentes de un contenedor y almacenar los resultados en otro contenedor.
Sintaxis:
template <InputIterator InIter, OutputIterator OutIter> OutIter adjacent_difference(InIter first, InIter last, OutIter result);
Ejemplo:
Ejemplo
#include <numeric>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4};
std::vector<int> result(v.size() - 1);
std::adjacent_difference(v.begin(), v.end(), result.begin());
for (int i : result) {
std::cout << i << " "; // Salida: 1 1 1
}
return 0;
}
5. std::gcd
Usa std::gcd para calcular el máximo común divisor de dos enteros:
Ejemplo
#include <numeric>
int main() {
int a = 48;
int b = 18;
int result = std::gcd(a, b); // Calcula el máximo común divisor de 48 y 18
std::cout << "GCD: " << result << std::endl; // Salida 6
return 0;
}
6. std::lcm
Usa std::lcm para calcular el mínimo común múltiplo de dos enteros:
Ejemplo
#include <numeric>
int main() {
int a = 48;
int b = 18;
int result = std::lcm(a, b); // Calcula el mínimo común múltiplo de 48 y 18
std::cout << "LCM: " << result << std::endl; // Salida 144
return 0;
}
7. std::iota
Ejemplo
#include <numeric> // incluye el archivo de cabecera numeric
#include <vector>
int main() {
std::vector<int> v(5); // Crea un vector con 5 elementos
// Usa std::iota para rellenar el vector, con valor inicial 1
std::iota(std::begin(v), std::end(v), 1);
// Imprime el vector rellenado
for (int i : v) {
std::cout << i << " ";
}
std::cout << std::endl; // Salida: 1 2 3 4 5
return 0;
}
Usa std::iota para rellenar los valores de una secuencia dentro de un rango.
template<class ForwardIt, class T> void iota(ForwardIt first, ForwardIt last, T value);
8. Encontrar el máximo y el mínimo
min_elementymax_elementLa función se utiliza para encontrar el valor máximo y el valor mínimo en un contenedor.
Ejemplo
#include <numeric>
#include <vector>
#include <algorithm> // para usar std::min_element y std::max_element
int main() {
// Define un vector de enteros
std::vector<int> v = {3, 1, 4, 1, 5, 9};
// Calcula el valor mínimo y el máximo
int min_val = *std::min_element(v.begin(), v.end());
int max_val = *std::max_element(v.begin(), v.end());
// Calcula la suma total
int sum_val = std::accumulate(v.begin(), v.end(), 0);
// Calcula el promedio
double avg_val = static_cast<double>(sum_val) / v.size();
// Imprime los resultados
std::cout << "Min: " << min_val << std::endl;
std::cout << "Max: " << max_val << std::endl;
std::cout << "Sum: " << sum_val << std::endl;
std::cout << "Average: " << avg_val << std::endl;
return 0;
}
El resultado de salida es:
Min: 1 Max: 9 Sum: 23 Average: 3.83333Otras extensiones