用 std::vector 存储阶乘更安全,因其动态扩容避免越界和内存浪费;需检查负数输入,0! 和 1! 均为 1;20! 以内可用 unsigned long long;手写循环比 std::tgamma 更精确。

用 std::vector 存储阶乘结果更安全
原生数组长度固定,而阶乘增长极快(13! 就超过 int 范围),硬编码数组大小容易越界或浪费内存。用 std::vector<long long></long> 或 std::vector<__int128></__int128>(GCC 扩展)能动态扩容,也方便后续遍历或传参。
常见错误是声明 int arr[100] 后对 i >= 13 的元素赋值,结果溢出为负数或 0,但编译器不报错。
- 输入数组含负数?阶乘无定义,需提前检查并跳过或报错
-
0!和1!都等于1,别漏掉这个边界 - 若输入最大值可能达
20,至少选unsigned long long(支持到20! = 2432902008176640000)
手写阶乘函数比调用库更可控
C++ 标准库没有通用阶乘函数,std::tgamma(n+1) 是浮点近似,对整数大值会丢失精度(如 tgamma(21) 可能返回 2432902008176640000.0 或 2432902008176639800.0),不能用于精确计算。
自己写循环更可靠:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
long long factorial(int n) {
if (n < 0) return -1; // 错误标记
long long res = 1;
for (int i = 2; i <= n; ++i) {
res *= i;
}
return res;
}- 别用递归——
factorial(100)会导致栈溢出 - 循环中不检查溢出,靠类型上限兜底;真要健壮可加
if (res > LLONG_MAX / i)判断 - 输入
n=0时循环不执行,res保持1,逻辑自然成立
批量计算时注意输入范围与性能
如果数组有上百个元素,且每个都要算阶乘,重复计算 5!、6! 等很浪费。可预计算最大 n 值以内的所有阶乘,存入查找表:
std::vector<long long> precompute_factorials(int max_n) {
std::vector<long long> fact(max_n + 1, 1);
for (int i = 2; i <= max_n; ++i) {
fact[i] = fact[i-1] * i;
}
return fact;
}- 先遍历输入数组得
max_n = *std::max_element(arr.begin(), arr.end()) - 若数组含
0或负数,max_n可能为负,需过滤后取最大非负值 - 查表法 O(1) 每次查询,总复杂度 O(N + max_n),比朴素 O(N × max_n) 快得多
输出或调试时别直接打印 long long 大数
某些旧环境(如 Windows + MinGW)的 printf 对 long long 支持不稳定,printf("%lld", val) 可能乱码或截断。
更稳妥的方式:
- 用
std::cout —— 流输出对整数类型兼容性好 - 若必须用
printf,确认编译器:GCC/Clang 用"%lld",MSVC 用"%I64d" - 调试时打印前加
if (val
真正麻烦的是超 unsigned long long 范围的情况——比如算 100!,这时必须上大数库(如 boost::multiprecision::cpp_int)或自己实现字符串乘法,不是改几个类型就能解决的。

















