当前位置: 首页 > news >正文

刷力扣用for求了无数次数组和?别急,numeric来救急

C++ 的<numeric>头文件主要包含用于数值计算算法处理的通用函数。虽然它的名字暗示它只处理数字,但其中的许多算法(如accumulate,inner_product)实际上是通过模板实现的,可以应用于任何支持特定运算符(如+,*)的用户自定义类型(例如矩阵、多项式或大整数类)。

在 C++17 和 C++20 中,这个库得到了显著增强,增加了并行执行支持和更多实用的数学工具。

首先就是我们的求和工具std::accumulate

  • 原型:T accumulate(Iter first, Iter last, T init);
  • 功能: 从init开始,依次将范围内的元素加到结果中。
  • 注意: 初始值init的类型决定了返回值的类型。如果处理整数但需要浮点结果,必须传入0.0而不是0
#include <iostream> #include <numeric> #include <vector> int main() { std::vector<int> nums = {1, 2, 3, 4, 5}; // 整数求和: 1+2+3+4+5 = 15 int sum_int = std::accumulate(nums.begin(), nums.end(), 0); // 浮点求和: 必须传入 0.0,否则会发生整数除法或截断 double sum_double = std::accumulate(nums.begin(), nums.end(), 0.0); // 自定义操作:计算乘积 (1*2*3*4*5 = 120) // C++17 起可以使用执行策略,但 accumulate 本身通常不带执行策略参数,需用 reduce //最后一个参数就代表归约为乘积计算,如果你想归约为加法就是std::plus<int>() int product = std::accumulate(nums.begin(), nums.end(), 1, std::multiplies<int>()); std::cout << "Sum: " << sum_int << ", Product: " << product << "\n"; return 0; }

这个库在C++17引入了并行与归约, reduce 与 transform_reduce (相关概念的解释在文末)

std::reducestd::transform_reduce的核心区别在于:是否在“归约(求和/累积)”之前,先对每个元素进行“变换(修改)”

#include <iostream> #include <numeric> #include <vector> #include <execution> // 并行执行策略 int main() { std::vector<int> large_data(1000000, 2); // 顺序执行 (类似 accumulate) auto sum_seq = std::reduce(large_data.begin(), large_data.end(), 0); // 并行执行 (利用多核 CPU) // std::execution::par 表示并行,std::execution::par_unseq 表示并行且无序 auto sum_par = std::reduce(std::execution::par, large_data.begin(), large_data.end(), 0); // Transform Reduce: 计算平方和 (2^2 + 2^2 + ...) auto sum_squares = std::transform_reduce( std::execution::par, large_data.begin(), large_data.end(), 0, // 初始值 std::plus<int>(), // 归约操作 (加) [](int x) { return x * x; } // 变换操作 (平方) ); std::cout << "Parallel Sum: " << sum_par << "\n"; return 0; }

可以看到,使用transform_reduce时,先修改每个数变成平方(lambda表达式)再执行归约

std::adjacent_difference 用于计算相邻元素的差值
  • 输出序列的第一个元素等于输入序列的第一个元素
#include <numeric> #include <vector> #include <iostream> int main() { std::vector<int> data = {1, 2, 4, 7, 11}; std::vector<int> diffs(data.size()); // 结果: {1, 2-1, 4-2, 7-4, 11-7} -> {1, 1, 2, 3, 4} std::adjacent_difference(data.begin(), data.end(), diffs.begin()); for (int n : diffs) std::cout << n << " "; std::cout << "\n"; return 0; }

std::partial_sum计算前缀和

输出序列的第 ii 个元素是输入序列前 i+1i+1 个元素的和

#include <numeric> #include <vector> #include <iostream> int main() { std::vector<int> nums = {1, 2, 3, 4}; std::vector<int> sums(nums.size()); std::partial_sum(nums.begin(), nums.end(), sums.begin()); for (int n : sums) std::cout << n << " "; // 输出: 1 3 6 10 return 0; }

除此之外,C++17引入了一些数学工具函数

  • std::gcd(a, b): 计算最大公约数 (Greatest Common Divisor)。
  • std::lcm(a, b): 计算最小公倍数 (Least Common Multiple)。
  • std::midpoint(a, b): 计算两个值的中间点,避免溢出
    • 传统写法(a + b) / 2ab很大时会溢出。

std::iota用于填充范围为连续递增的值。

作用: 将范围[first, last)填充为value, value+1, value+2...

#include <numeric> #include <vector> #include <iostream> int main() { std::vector<int> indices(5); // 填充为 0, 1, 2, 3, 4 std::iota(indices.begin(), indices.end(), 0); for (int i : indices) std::cout << i << " "; return 0; }

什么是执行策略,并行,归约?

旨在让标准库算法(如sort,reduce,for_each)能够利用多核 CPU 加速运行。

  • 执行策略 (Execution Policy):你告诉算法“可以怎么跑”(串行、并行、还是向量化)。
  • 并行 (Parallel):算法实际利用多个线程同时工作的状态。
  • 归约 (Reduction):一种将一堆数据“压缩”成一个结果的计算模式(如求和、求最大值),它是并行计算中最常见的操作。

在 C++17 之前,标准算法(如std::sort)只能是单线程顺序执行的。C++17 允许你在调用算法时传入一个执行策略对象作为第一个参数,以此指示库是否可以并行执行。

这些策略定义在<execution>头文件中,属于std::execution命名空间。

四种主要策略:

表格

策略对象名称含义适用场景注意事项
std::execution::seq顺序执行强制单线程。行为与 C++17 之前的算法完全一致。需要严格顺序依赖的操作;调试时。无额外开销,最安全。
std::execution::par并行执行允许多线程。算法可以将任务拆分到多个线程运行,但每个线程内的操作必须按顺序执行大部分可并行化的任务(如排序、查找)。数据竞争危险:如果操作涉及共享状态,需自行加锁或使用原子操作。
std::execution::par_unseq并行且无序允许多线程 + 向量化 (SIMD)。不仅可以在不同线程间并行,还可以在一个线程内通过 CPU 指令集(如 AVX)对数据进行向量化处理,且不保证元素访问顺序高性能数值计算、图像处理。限制最严:不能使用互斥锁,不能依赖元素访问顺序,不能有异常抛出(通常会导致std::terminate)。
std::execution::unseq无序执行 (C++20)仅允许向量化,不允许多线程。单线程内的 SIMD 优化。较少直接使用,通常由编译器自动优化或配合par_unseq
#include <algorithm> #include <vector> #include <execution> // 必须包含 void example() { std::vector<int> v = {5, 2, 9, 1, 5, 6}; // 1. 顺序执行 (传统方式) std::sort(v.begin(), v.end()); // 2. 并行执行 (可能使用多线程) std::sort(std::execution::par, v.begin(), v.end()); // 3. 并行 + 向量化 (最快,但限制最多) std::sort(std::execution::par_unseq, v.begin(), v.end()); }

归约是一种函数式编程概念,指将一个序列(集合)通过某种二元操作(如加法、乘法、取最大值),逐步合并成单个值的过程。

  • 常见例子:求和 (sum)、求积 (product)、求最大值 (max)、逻辑与 (all_of)。
C++ 中的归约算法:std::reduce
  • std::accumulate严格顺序执行。 (((init+v0)+v1)+v2)...(((init+v0​)+v1​)+v2​)...
  • std::reduce无序执行。它允许以任意顺序组合元素,以便并行。

重要约束:使用std::reduce时,你的操作符必须满足交换律结合律

就比如我们刚才使用accumulate或transfrom_reduce最后一个参数,那个就是你只要指定的归约

(accumulate和reduce如果不显示指定归约默认就是plus)

加法std::plus<T>a+b求和 (最常用)
乘法std::multiplies<T>a×b求积 (阶乘、概率连乘)
最大值std::maximum<T>max⁡(a,b)找最大值
最小值std::minimum<T>min⁡(a,b)找最小值
逻辑与std::logical_and<T>a∧b检查是否所有元素都满足条件
逻辑或std::logical_or<T>a∨b检查是否存在元素满足条件
按位与std::bit_and<T>a & b位运算掩码
按位或std::bit_or<T>$ a \\ b $
http://www.jsqmd.com/news/543046/

相关文章:

  • 昆仑通态MCGS与西门子S7-200/200SMART PLC通讯及控制台达变频器技术解析
  • 推荐算法数学概念-向量-矩阵-损失函数-梯度下降
  • 帮老人远程点清淡外卖全攻略:地址设置+餐品选择+优惠指南 - 速递信息
  • 【数据结构与算法】第7篇:线性表(三):单链表的经典面试题(反转、找中间节点)
  • 个人开发者如何高效率APP上架安卓应用市场?软著、备案、资质、审核详解大全,一篇文章讲透流程规则!
  • 选吉他不踩坑:合板、单板、全单材质深度解析,新手看懂这篇就够
  • 42-西门子1200伺服控制5轴程序 程序采用1200系列PLC,项目实现以下功能: (1)
  • vLLM-v0.17.1实操手册:vLLM在Mac M2 Ultra上通过ROCm模拟运行
  • 如何快速回收微信立减金闲置资源?全攻略解析 - 团团收购物卡回收
  • 告别碎片化工具链:用Cube-Studio统一管理你的开源大模型(从ChatGLM到Llama3)
  • 目标检测损失函数进化史:从IoU到EIoU/SIoU/WIoU,YOLOv8性能提升完全指南
  • 【FreeRTOS实战入门】一、从CubeMX到第一个任务:手把手搭建FreeRTOS工程
  • 零成本搞数字化!免费低代码工具(斑斑AI vs 宜搭)测评
  • iOS18适配避坑指南:Xcode16编译报错全解析(含YYCache、ADClient修复方案)
  • 校园外卖配送范围查询及门口自取设置全攻略 - 速递信息
  • YOLOv12学术论文写作:使用LaTeX排版技术报告与实验图表
  • Llama-3.2V-11B-cot效果实测:同一张图不同提问下的CoT推理路径对比分析
  • 带娃宅家点外卖安全健康攻略:从商家筛选到餐品搭配全指南 - 速递信息
  • 如何通过解析技术获取百度网盘真实下载链接
  • 轻量系统构建:用tiny11builder打造高效Windows 11精简版
  • 构建可扩展的翻译引擎:Zotero PDF Translate插件架构深度解析
  • LED选型避坑指南:从电源指示灯到全彩显示,这些参数你考虑了吗?
  • Windows远程桌面多用户破解:RDP Wrapper终极配置指南
  • 计算机软件著作权登记证书、电子版权、软件著作权是什么关系
  • 深入TC397与TLF35584的SPI通信:从寄存器操作到汽车ECU低功耗状态管理实战
  • 【开源鸿蒙Flutter跨平台开发实战复盘】从零到一:GitCode口袋工具项目构建全记录
  • .mtl文件路径报错怎么办?Unity中修复白模问题的3种实战方案
  • vLLM-v0.17.1惊艳效果:束搜索+并行采样在长文本生成中的稳定性展示
  • 保姆级教程:用QPST+QFIL给小米/一加备份基带qcn文件(防丢失IMEI必备)
  • Taskbar-Lyrics:Windows 11任务栏歌词嵌入工具让音乐体验升级