std::gcd最快且安全,但需C++17支持;手写推荐迭代版,避免栈溢出与符号问题;注意abs(INT_MIN)溢出及类型匹配。

用 std::gcd 最快,但要注意 C++17 起才支持
如果你的编译器支持 C++17(如 GCC 8+、Clang 7+、MSVC 2017 Update 5+),直接调用标准库函数最省事:
std::gcd(a, b)它自动处理符号(返回非负结果)、零值(
std::gcd(a, 0) == abs(a)),且内部通常用汇编优化。但注意:参数必须是整型,且不能是浮点或自定义类型。
手写辗转相除法:递归写法简洁,但栈深可能溢出
核心逻辑是反复用大数对小数取余,直到余数为 0。递归实现直观:
int gcd(int a, int b) {
return b == 0 ? abs(a) : gcd(b, a % b);
}
-
a % b的符号依赖于被除数a(C++ 中负数取模结果可为负),所以最终返回前加abs() - 递归深度最坏是 O(log min(|a|,|b|)),对极大数(如接近
INT_MAX)仍安全;但若编译器未开启尾递归优化,极端情况可能栈溢出 - 避免传入两个 0 —— 会导致无限递归(
gcd(0,0)数学上无定义)
手写辗转相除法:迭代写法更可控,推荐生产环境使用
迭代避免了函数调用开销和栈风险,逻辑也更贴近硬件执行流程:
int gcd(int a, int b) {
a = abs(a);
b = abs(b);
while (b != 0) {
int r = a % b;
a = b;
b = r;
}
return a;
}
- 一开始就用
abs()统一转正,后续所有%运算都安全,无需在循环中反复判断符号 - 循环体仅含三步赋值,CPU 流水线友好,现代编译器容易内联
- 如果输入含
0(如gcd(0, 5)),第一轮就跳出,返回5,符合数学定义
边界与类型问题:别让 int 溢出毁掉整个计算
辗转相除法本身不产生中间大数,但若原始输入是 long long,而你用 int 接收,会截断出错。更隐蔽的是:当其中一个数是 INT_MIN 时,abs(INT_MIN) 在二进制补码下溢出(仍是 INT_MIN)。
立即学习“C++免费学习笔记(深入)”;
- 处理大整数务必匹配类型:用
long long就全用long long,别混用 - 安全取绝对值可改用
llabs()(对long long)或手动判断:if (a == INT_MIN) a = INT_MAX; // 不推荐,仅作示意
实际应优先用无符号类型或检查输入范围 - 若需支持任意精度,得换用
boost::multiprecision或自己实现大数取模











