Стандартная библиотека C++<numeric>
В повседневной разработке на C++ мы часто сталкиваемся со следующими требованиями:
- Вычислить сумму / произведение массива
- Вычислить префиксные суммы для запросов по диапазону
- Пакетное накопление для создания новой последовательности
- Вычислить внутреннее произведение (скалярное произведение) между векторами
Если вы всё ещё пишете это вручнуюforЦикл, затем<numeric>Это именно те инструменты стандартной библиотеки, которыми вам следует овладеть.
В стандартной библиотеке C++<numeric>Заголовочный файл предоставляет набор шаблонов функций для численных вычислений. Эти функции могут выполнять различные численные операции над элементами контейнера, такие как суммирование, произведение, минимум, максимум и т. д. Эти шаблоны функций чрезвычайно мощны и могут применяться к любому типу контейнера, включая массивы, векторы, списки и так далее.
При использовании<numeric>Прежде чем использовать функции из заголовочного файла, вам нужно включить этот заголовочный файл в вашу программу на C++:
#include <numeric>
Общие функции
<numeric>так C++ обрабатываетвычисление числовых последовательностейЭто основной заголовочный файл, ориентированный на такие операции, как редукция, накопление и разность, и совместим со всеми контейнерами STL;- Базовые функции (
accumulate/partial_sum/iotaЭто ядро C++98/11, удовлетворяющее большинству обычных потребностей в численных вычислениях; - добавлено в C++17
reduce/inclusive_scanТакие параллельные функции могут значительно повысить эффективность вычислений при больших объёмах данных, и их нужно использовать с политиками параллельного выполнения.
| Имя функции | Версия C++ | Основные функции | Упрощённый прототип функции (взявvector<int>в качестве примера) |
типичные варианты использования |
|---|---|---|---|---|
accumulate |
C++98 | Вычисляет кумулятивную сумму последовательности (можно указать пользовательскую бинарную операцию) | int accumulate(iterator beg, iterator end, int init); |
Вычисление суммы массива, накопление статистики |
inner_product |
C++98 | Вычисляет скалярное произведение двух последовательностей (перемножает соответствующие элементы и затем суммирует; можно указать пользовательские операции) | int inner_product(iter1 b1, iter1 e1, iter2 b2, int init); |
Скалярное произведение векторов, взвешенная сумма |
partial_sum |
C++98 | Вычисляет префиксные суммы последовательности (n-й результат = сумма первых n элементов, настраиваемая операция) | void partial_sum(iter b, iter e, iter res); |
Генерация массива префиксных сумм, накопление статистики |
adjacent_difference |
C++98 | Вычисляет разности между соседними элементами последовательности (n-й результат = elem[n] - elem[n-1], настраиваемая операция) | void adjacent_difference(iter b, iter e, iter res); |
Вычисление разностей, обнаружение изменений последовательности |
iota |
C++11 | Заполняет последовательность непрерывно возрастающими значениями (начиная с init, увеличивая на 1 каждый раз) | void iota(iter b, iter e, T init); |
Генерирует последовательность идущих подряд целых чисел, инициализирует упорядоченные контейнеры |
reduce |
C++17 | Параллельная версия accumulate (аналогично accumulate, поддерживает параллельное выполнение, неупорядоченная редукция) | T reduce(iter b, iter e, T init = T{}); |
Параллельное суммирование для больших объёмов данных, повышающее вычислительную эффективность |
transform_reduce |
C++17 | Преобразование + редукция (сначала преобразуются элементы, затем выполняется накопление, поддерживается параллельное выполнение) | T transform_reduce(iter1 b1, iter1 e1, iter2 b2, T init); |
Параллельное скалярное произведение, сумма после преобразования |
inclusive_scan |
C++17 | Параллельная префиксная сумма (включая текущий элемент, аналогично partial_sum, поддерживает параллельное выполнение) | void inclusive_scan(iter b, iter e, iter res); |
Параллельная генерация массивов префиксных сумм |
exclusive_scan |
C++17 | Параллельная версия префиксной суммы (исключая текущий элемент; n-й результат = сумма первых n-1 элементов) | void exclusive_scan(iter b, iter e, iter res, T init); |
Параллельная генерация префиксных сумм, не включающих текущий элемент |
1. accumulate
accumulateФункция используется для вычисления суммы всех элементов в контейнере. Она принимает три параметра: начальный итератор контейнера, конечный итератор и начальное значение.
Синтаксис:
template <InputIterator Iter, class T> T accumulate(Iter first, Iter last, T init);
Пример:
Пример
#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 << std::endl; // Вывод: Sum: 15
return 0;
}
2. inner_product
inner_productФункция используется для вычисления суммы произведений соответствующих элементов в двух контейнерах.
Синтаксис:
template <InputIterator1 Iter1, InputIterator2 Iter2, class T> T inner_product(Iter1 first1, Iter1 last1, Iter2 first2, T init);
Пример:
Пример
#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; // Вывод: Product Sum: 32
return 0;
}
3. partial_sum
partial_sumФункция вычисляет частичные суммы элементов контейнера и сохраняет результаты в другом контейнере.
Синтаксис:
template <InputIterator InIter, OutputIterator OutIter> OutIter partial_sum(InIter first, InIter last, OutIter result);
Пример:
Пример
#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 << " "; // Вывод: 1 3 6 10
}
return 0;
}
4. adjacent_difference
adjacent_differenceФункция вычисляет разности соседних элементов в контейнере и сохраняет результаты в другом контейнере.
Синтаксис:
template <InputIterator InIter, OutputIterator OutIter> OutIter adjacent_difference(InIter first, InIter last, OutIter result);
Пример:
Пример
#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 << " "; // Вывод: 1 1 1
}
return 0;
}
5. std::gcd
Используйте std::gcd для вычисления наибольшего общего делителя двух целых чисел:
Пример
#include <numeric>
int main() {
int a = 48;
int b = 18;
int result = std::gcd(a, b); // Вычислите наибольший общий делитель чисел 48 и 18
std::cout << "GCD: " << result << std::endl; // Вывод 6
return 0;
}
6. std::lcm
Используйте std::lcm для вычисления наименьшего общего кратного двух целых чисел:
Пример
#include <numeric>
int main() {
int a = 48;
int b = 18;
int result = std::lcm(a, b); // Вычислите наименьшее общее кратное чисел 48 и 18
std::cout << "LCM: " << result << std::endl; // Вывод 144
return 0;
}
7. std::iota
Пример
#include <numeric> // Подключение заголовочного файла numeric
#include <vector>
int main() {
std::vector<int> v(5); // Создайте вектор, содержащий 5 элементов
// Заполните вектор с помощью std::iota, начиная с 1
std::iota(std::begin(v), std::end(v), 1);
// Выведите заполненный вектор
for (int i : v) {
std::cout << i << " ";
}
std::cout << std::endl; // Вывод: 1 2 3 4 5
return 0;
}
Используйте std::iota для заполнения диапазона последовательными значениями.
template<class ForwardIt, class T> void iota(ForwardIt first, ForwardIt last, T value);
8. Поиск максимального и минимального значений
min_elementиmax_elementФункция используется для поиска максимального и минимального значений в контейнере.
Пример
#include <numeric>
#include <vector>
#include <algorithm> // Для использования std::min_element и std::max_element
int main() {
// Определите вектор целых чисел
std::vector<int> v = {3, 1, 4, 1, 5, 9};
// Вычислить минимальное и максимальное значения
int min_val = *std::min_element(v.begin(), v.end());
int max_val = *std::max_element(v.begin(), v.end());
// Вычислить сумму
int sum_val = std::accumulate(v.begin(), v.end(), 0);
// Вычислить среднее значение
double avg_val = static_cast<double>(sum_val) / v.size();
// Вывод результатов
std::cout << "Минимум: " << min_val << std::endl;
std::cout << "Максимум: " << max_val << std::endl;
std::cout << "Сумма: " << sum_val << std::endl;
std::cout << "Среднее: " << avg_val << std::endl;
return 0;
}
Результат вывода:
Min: 1 Max: 9 Sum: 23 Average: 3.83333Другие расширения