用std::gcd配合std::reduce一行可求数组GCD(C++17+),需包含<numeric>,确保非全零,因std::gcd(a,0)=|a|而gcd(0,0)=0仅为实现约定。

用 std::gcd 配合 std::reduce 一行搞定(C++17+)
标准库从 C++17 开始提供 std::gcd,但它只接受两个整数。对数组求 GCD,本质是把二元操作「折叠」到整个序列上——std::reduce(需 <numeric>)就是干这个的。
- 必须确保所有元素非零;若含 0,
std::gcd(a, 0)返回abs(a),但全零数组无定义 GCD,需提前检查 -
std::reduce默认使用加法结合律,GCD 满足结合律和交换律,可安全并行(但小数组没必要开并行) - 示例:
#include <numeric> #include <algorithm> #include <vector> #include <cmath> int arr[] = {48, 18, 24}; int n = sizeof(arr) / sizeof(arr[0]); int result = std::reduce(arr, arr + n, arr[0], std::gcd<int>); // 得 6
手写 GCD 函数时,注意负数和边界值
std::gcd 内部已处理负数(返回非负结果),但自己实现欧几里得算法时容易漏掉 abs。
- 错误写法:
gcd(a, b) { return b == 0 ? a : gcd(b, a % b); }—— 若a为负,递归可能陷入负余数循环或未定义行为 - 正确做法:始终对输入取绝对值,或在递归前做
abs,例如:return gcd(std::abs(b), std::abs(a % b)) - 空数组或单元素数组要单独处理:空数组无意义;单元素 GCD 就是其绝对值
数组含 0 或负数时,GCD 的数学含义要明确
GCD 在整数范围通常定义为「最大的正整数,能整除所有给定整数」。这意味着:
- 数组中出现 0 不影响结果,因为任何整数都能整除 0;GCD 实际由非零元素决定(如
{0, 12, 18}的 GCD 是 6) - 负数不影响结果,GCD 定义本身基于绝对值;
gcd(-12, 8)和gcd(12, 8)都是 4 - 但若数组全为 0,数学上 GCD 无定义;代码中
std::gcd(0, 0)返回 0,这属于实现约定,不是数学共识——务必根据业务判断是否允许全零输入
旧标准(C++14 及以前)怎么兼容
没有 std::gcd 和 std::reduce,只能手写循环 + 自定义 GCD 函数。
立即学习“C++免费学习笔记(深入)”;
- 用
for循环逐个更新当前 GCD 值,初始值设为第一个非零元素的绝对值 - 跳过 0(因
gcd(g, 0) == g),但需先确认至少有一个非零数 - 示例片段:
int my_gcd(int a, int b) { a = std::abs(a); b = std::abs(b); while (b != 0) { int r = a % b; a = b; b = r; } return a; } int arr[] = {0, -45, 30}; int res = 0; for (int x : arr) { if (x != 0) { res = res == 0 ? std::abs(x) : my_gcd(res, x); } }


















