信息发布→ 登录 注册 退出

c++中如何求一个数的阶乘_c++递归与循环实现阶乘

发布时间:2026-01-07

点击量:
阶乘递归易致栈溢出和整数溢出,int仅支持到12!,unsigned long long最多到20!;循环实现更安全可控,需校验乘法是否越界并返回错误码。

int 递归写阶乘会很快溢出

递归实现看起来简洁,但实际使用中必须警惕整数溢出和栈溢出。C++ 标准不保证尾递归优化,factorial(10000) 这种调用大概率触发 stack overflow。更现实的问题是:int 在大多数平台下最大值约 21 亿,factorial(13) 就已超限(13! = 6227020800)。若真需要大数阶乘,得换容器或库,比如 unsigned long long 最多撑到 factorial(20)

循环实现更安全、更可控

循环避免了函数调用开销和栈风险,也方便做边界检查和提前退出。关键点在于初始值设为 1,且循环从 2 开始(1!0! 都是 1)。

long long factorial(int n) {
    if (n < 0) return -1; // 无效输入
    long long result = 1;
    for (int i = 2; i <= n; ++i) {
        if (result > LLONG_MAX / i) return -1; // 溢出预检
        result *= i;
    }
    return result;
}
  • n == 0n == 1 时,for 循环不执行,直接返回 1
  • 溢出检查用 LLONG_MAX / i 而不是 result * i > LLONG_MAX,防止乘法本身已越界
  • 返回 -1 表示错误,调用方需判断,不能默认结果一定有效

递归版本只适合教学或小范围验证

如果坚持用递归,至少要加输入校验,并明确限定安全范围(比如 n )。否则看似优雅,实则隐藏运行时崩溃风险。

long long factorial_recursive(int n) {
    if (n < 0) return -1;
    if (n > 20) return -1; // 明确拒绝高风险输入
    if (n <= 1) return 1;
    return n * factorial_recursive(n - 1);
}
  • 没有尾递归优化的编译器(如 GCC 默认未开启 -O2 以上)对 factorial_recursive(20) 也会产生 20 层调用
  • 每次调用都压栈参数和返回地址,空间复杂度 O(n),而循环是 O(1)
  • 调试时递归栈帧容易掩盖真实问题,比如忘了处理 n == 0

别忽略 0! 的定义和类型选择

数学上 0! == 1,代码里必须显式支持,不能靠循环“跳过”。另外,返回类型不能拍脑袋选 int —— 即使只算到 10!3628800),在嵌入式或旧系统上 int 可能只有 16 位(最大 32767),10! 就已溢出。

立即学习“C++免费学习笔记(深入)”;

  • 保守起见,输入 int n,返回用 long long,并文档注明“仅支持 n ∈ [0, 20]
  • 若需更大范围,必须引入 std::vector 手动模拟大数乘法,或用 boost::multiprecision
  • 模板化不是万能解药:template T factorial(int n) 无法自动规避底层类型的溢出

实际项目里,阶乘很少孤立存在;它常是组合数、泰勒展开等的一部分。这时候更该考虑是否真的需要完整阶乘值,还是可以边算边约分——那才是真正的性能关键点。

标签:# 最多  # 跳过  # 才是真正  # 问题是  # 设为  # 更大  # 也会  # 都是  # 泰勒  #   # 循环  # int  # 阶乘  # 递归  # for  # overflow  # c++  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!