如何用STL容器与算法库实现类Python风格的向量内积计算?
C++ 中类似 Python 风格的向量内积实现
当然有啦!借助C标准库的<algorithm>和<numeric>(以及C20新增的范围库),完全能写出像Python那样简洁、优雅的向量内积代码,不用再手写繁琐的循环。下面给你几种常用的实现方式:
1. 最直接的:用std::inner_product
这是标准库专门为计算内积设计的函数,一步到位,代码最简洁:
#include <numeric> // 必须包含这个头文件 // 假设v1和v2是两个同类型的向量,比如std::vector<double> auto inner_product_result = std::inner_product(v1.begin(), v1.end(), v2.begin(), 0.0);
- 前两个参数是第一个向量的首尾迭代器,第三个参数是第二个向量的起始迭代器,最后一个是累加的初始值(这里用
0.0而非0,避免整数类型的截断问题)。 - 注意:如果第二个向量的长度比第一个短,会导致未定义行为,所以最好先断言两个向量长度相等:
assert(v1.size() == v2.size());
2. 贴近Python zip风格:用C++20范围库
如果你更偏爱Python那种「zip配对→元素相乘→累加」的思路,C++20的范围库可以完美复刻这个逻辑:
#include <ranges> #include <numeric> auto inner_product_result = std::accumulate( // 用zip把v1和v2的对应元素配对,再transform相乘 std::views::zip(v1, v2) | std::views::transform([](auto&& pair) { return std::get<0>(pair) * std::get<1>(pair); }), 0.0 // 初始累加值 );
std::views::zip和Python的zip功能几乎一样,会将两个序列的对应元素打包成配对;std::views::transform负责对每一对元素执行相乘操作;- 最后用
std::accumulate完成累加,整个流程和你给出的Python代码acc = accumulate([ele1 * ele2 for ele1, ele2 in zip(v1, v2)])完全对应。 - 这种写法下,
zip会自动取两个序列中较短的长度,和Python的行为一致,如果需要严格检查长度,同样可以先加断言。
3. 兼容旧标准:std::transform + std::accumulate
如果你的项目还不能用C++20,也可以结合std::transform和std::accumulate来实现,只是需要一个临时容器存储相乘后的结果:
#include <algorithm> #include <numeric> #include <vector> std::vector<double> products(v1.size()); std::transform(v1.begin(), v1.end(), v2.begin(), products.begin(), [](double a, double b) { return a * b; }); auto inner_product_result = std::accumulate(products.begin(), products.end(), 0.0);
虽然多了一步临时容器的创建,但同样避免了手写循环,可读性也不错。
总的来说,这些标准库算法不仅写法简洁,还能利用编译器的优化,性能上不会比手写循环差,甚至可能更优。
内容的提问来源于stack exchange,提问作者Liu Weibo
相关产品推荐
相关产品推荐

