C++标准库中的<numeric>
头文件提供了一系列用于数值计算的函数模板,这些函数可以对容器中的元素进行各种数值操作,如求和、乘积、部分和、内积、相邻元素差等。以下是关于<numeric>
头文件的功能、用法及详细解析:
一、功能概述
<numeric>
头文件主要包含以下核心函数:
std::accumulate
:用于计算序列中元素的累积和(或其他累积操作)。std::inner_product
:计算两个序列的内积。std::adjacent_difference
:计算序列中相邻元素的差。std::partial_sum
:生成一个包含序列部分和的序列。std::iota
:生成从指定初始值开始的连续递增序列(填充容器)。
此外,C++17及以后的版本还引入了std::reduce
和std::transform_reduce
等函数,进一步扩展了<numeric>
的功能,支持并发计算和结合变换操作。不过,这里主要基于C++11标准讲解前五个函数的用法。
二、详细用法及解析
1. std::accumulate
- 功能:计算序列中所有元素的累积和,或者以自定义的方式累积元素。
- 语法:
template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init);template<class InputIt, class T, class BinaryOperation>
T accumulate(InputIt first, InputIt last, T init, BinaryOperation op);
-
参数:
first
、last
:表示输入序列的范围。init
:累积计算的初始值。op
:可选的二元操作函数,用于指定累积规则。
-
示例:
#include <iostream>
#include <numeric>
#include <vector>int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};int sum = std::accumulate(numbers.begin(), numbers.end(), 0); // 初始值为0std::cout << "Sum: " << sum << std::endl; // 输出: Sum: 15// 计算累积的乘积int product = std::accumulate(numbers.begin(), numbers.end(), 1, [](int a, int b) { return a * b; });std::cout << "Product: " << product << std::endl; // 输出: Product: 120return 0;
}
2. std::inner_product
- 功能:计算两个序列的内积(dot product)。默认操作是计算两个序列中对应元素的乘积,并将结果相加,也可以通过自定义操作实现更复杂的计算。
- 语法:
template<class InputIt1, class InputIt2, class T>
T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init);template<class InputIt1, class InputIt2, class T, class BinaryOperation1, class BinaryOperation2>
T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init, BinaryOperation1 op1, BinaryOperation2 op2);
-
参数:
first1
、last1
:第一个输入序列的范围。first2
:第二个输入序列的起始位置。init
:内积计算的初始值。op1
、op2
:自定义的二元操作函数,用于元素间的操作和累积规则。
-
示例:
#include <iostream>
#include <numeric>
#include <vector>int main() {std::vector<int> vec1 = {1, 2, 3};std::vector<int> vec2 = {4, 5, 6};int dotProduct = std::inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0);std::cout << "Dot product: " << dotProduct << std::endl; // 输出: Dot product: 32return 0;
}
3. std::adjacent_difference
- 功能:计算序列中相邻元素的差值,并将结果存储在另一个容器中。
- 语法:
template<class InputIt, class OutputIt>
OutputIt adjacent_difference(InputIt first, InputIt last, OutputIt result);template<class InputIt, class OutputIt, class BinaryOperation>
OutputIt adjacent_difference(InputIt first, InputIt last, OutputIt result, BinaryOperation op);
-
参数:
first
、last
:输入序列的范围。result
:存储结果的容器的起始迭代器。op
:可选的二元操作函数,用于指定相邻元素间的操作。
-
示例:
#include <iostream>
#include <numeric>
#include <vector>int main() {std::vector<int> nums = {1, 3, 6, 10, 15};std::vector<int> diffs(nums.size());std::adjacent_difference(nums.begin(), nums.end(), diffs.begin());for (size_t i = 0; i < diffs.size(); ++i) {std::cout << diffs[i] << " "; // 输出: 1 2 3 4 5}std::cout << std::endl;return 0;
}
注意:diffs[0]
总是等于nums[0]
,因为前面没有元素来形成差值。
4. std::partial_sum
- 功能:计算序列中元素的部分和,并将结果存储在另一个容器中。
- 语法:
template<class InputIt, class OutputIt>
OutputIt partial_sum(InputIt first, InputIt last, OutputIt result);template<class InputIt, class OutputIt, class BinaryOperation>
OutputIt partial_sum(InputIt first, InputIt last, OutputIt result, BinaryOperation op);
-
参数:
first
、last
:输入序列的范围。result
:存储结果的容器的起始迭代器。op
:可选的二元操作函数,用于指定部分和的计算规则。
-
示例:
#include <iostream>
#include <numeric>
#include <vector>int main() {std::vector<int> nums = {1, 2, 3, 4, 5};std::vector<int> partialSums(nums.size());std::partial_sum(nums.begin(), nums.end(), partialSums.begin());for (int sum : partialSums) {std::cout << sum << " "; // 输出: 1 3 6 10 15}std::cout << std::endl;return 0;
}
5. std::iota
- 功能:生成从指定初始值开始的连续递增序列(填充容器)。
- 语法:
template<class ForwardIt, class T>
void iota(ForwardIt first, ForwardIt last, T value);
-
参数:
first
、last
:要填充的容器的范围。value
:起始值。
-
示例:
#include <iostream>
#include <numeric>
#include <vector>int main() {std::vector<int> vec(5);std::iota(vec.begin(), vec.end(), 0); // 从0开始填充for (int val : vec) {std::cout << val << " "; // 输出: 0 1 2 3 4}std::cout << std::endl;return 0;
}
三、总结
<numeric>
头文件提供了丰富的函数,可以简化在C++中进行数值计算的任务。这些函数大多是基于迭代器的,因此与STL容器的兼容性非常好。通过熟练使用这些函数,可以提高编程效率和代码质量。