std::partial_sum配合std::multiplies()可直接计算累积乘积,需包含<numeric>和<functional>,输入需随机访问迭代器,输出不可与输入重叠(除非原地操作),初始值为1;手动循环在需溢出检查、提前终止或自定义类型时更稳妥。

std::partial_sum 配合乘法仿函数最直接
标准库 std::partial_sum 本意是算前缀和,但支持自定义二元操作符,传入 std::multiplies() 就能自然得到累积乘积。它原地计算或写入目标区间,语义清晰、无手写循环的边界风险。
- 必须包含头文件
<numeric>和<functional> - 输入范围需为随机访问迭代器(普通数组、
std::vector都满足) - 输出容器(或起始迭代器)不能与输入重叠,除非你明确用原地版本(即输出指针等于输入起始)
- 示例:
int arr[] = {2, 3, 4, 5};<br>int result[4];<br>std::partial_sum(arr, arr + 4, result, std::multiplies<>());<br>// result == {2, 6, 24, 120}
手动循环更可控,尤其要处理零或溢出时
当需要提前终止(比如遇到 0 后全截断)、检查整数溢出、或适配非标准类型(如自定义大数类)时,手写循环反而更稳妥。标准库不校验溢出,也不提供中断机制。
- 注意初始值设为
1,不是0(乘法单位元) - 若数组为空,循环不执行,结果数组应预先置空或跳过
- 对
unsigned long long等类型,可用__builtin_mul_overflow(GCC/Clang)检测溢出 - 示例片段:
std::vector<long long> v = {2, 0, 4, 5};<br>std::vector<long long> prod(v.size());<br>if (!v.empty()) {<br> prod[0] = v[0];<br> for (size_t i = 1; i < v.size(); ++i) {<br> prod[i] = prod[i-1] * v[i]; // 此处可能溢出或下溢<br> }<br>}
std::inclusive_scan(C++17 起)是更现代的替代
std::inclusive_scan 是 std::partial_sum 的泛化,明确支持任意二元操作,语义更准确(“包含当前元素”的扫描),且对并行执行有预留接口(虽实际并行需额外策略)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 同样需
<numeric>,用法几乎一致:std::inclusive_scan(first, last, out, std::multiplies()) - 在 C++17 及以上可安全使用;若项目锁死在 C++11/14,仍用
std::partial_sum - 和
partial_sum一样,不处理溢出、不跳过零——这些仍是业务逻辑责任
别忽略数值特性:零、负数、浮点精度
累积乘积不是纯算法问题,更是数值问题。一个 0 会让后续所有结果为 0;奇数个负数导致符号翻转;浮点数连续相乘会快速积累舍入误差。
立即学习“C++免费学习笔记(深入)”;
- 若业务允许,可预扫数组:记录首个
0位置,之后直接填0,避免无效计算 - 对浮点型(
float/double),考虑用 Kahan 求和式的思想做补偿乘法(虽少见,但高精度场景存在) - 用
std::log转加法再指数还原(exp(sum(log(x))))可缓解下溢,但引入新误差且不适用于 ≤ 0 输入
实际写的时候,多数情况用 std::partial_sum 最省心;但只要涉及零值语义、溢出防护或调试需求,就得切回手动循环——库函数不会替你决定“遇到零还继续乘有没有意义”。

















