用for循环算阶乘最稳:初始化$result=1,从$i=2开始循环;输入需校验非负整数,大数用bcmul,0和1直接返回1,避免溢出与静默错误。

PHP里用for循环算阶乘,怎么写才不翻车
直接说结论:用 for 循环算阶乘最稳,但别从 0 开始乘、别用 int 存大数、别忘了边界判断。
常见错误是输入 0 或 1 时结果为 0,或者算到 13! 就溢出——PHP 默认整型在 32 位系统上最大约 21 亿,13! = 6227020800 已超限。
-
$n = 0或$n = 1时,阶乘定义是 1,循环体必须跳过或单独处理 - 建议初始化结果为
$result = 1,然后从$i = 2开始循环,避免乘 0 或无效迭代 - 如果要支持大于 12 的数,改用
bcadd/bcmul(如bcmul($result, $i)),否则会静默转成浮点甚至科学计数法,丢失精度
递归实现阶乘时,PHP容易爆栈或返回null
递归写法看着简洁,但 PHP 默认栈深度有限(一般 100 层左右),算 factorial(200) 直接报 Fatal error: Maximum function nesting level;更隐蔽的问题是没写终止条件,比如漏了 if ($n ,会导致无限调用。
- 必须显式处理
$n 的情况,返回 <code>1,不能只写$n == 1,否则0输入会进递归分支 - 非必要别用递归算阶乘——它比循环慢、占栈、难调试;仅适合教学演示或配合记忆化(memoization)做高频小范围查表
- 如果真要用,加个保护:
if ($n > 100) throw new InvalidArgumentException('n too large for recursion');
阶乘函数要不要校验输入?不校验会出什么问题
不校验就等于把雷留给调用方。PHP 不会自动拒绝负数、字符串或 null,factorial(-5) 可能死循环,factorial("3") 看似能转成 int,但 factorial("3.7") 会变成 factorial(3)——隐式转换藏坑。
立即学习“PHP免费学习笔记(深入)”;
- 用
is_int($n)+$n >= 0双重判断,比is_numeric()安全 - 对字符串输入,明确拒绝:
if (is_string($n) && !ctype_digit($n)) { throw new InvalidArgumentException('n must be non-negative integer'); } - 注意:PHP 8+ 支持
int类型声明,但只能约束传参类型,拦不住factorial(3.0)这种 float,仍需手动检查值域
性能差别大吗?for vs 递归 vs 扩展函数
纯计算场景下,for 循环比递归快 3–5 倍(实测 10000 次调用),且内存稳定;而 bcmul 版本虽然精度高,但慢 10 倍以上——不是所有场景都需要高精度。
- 日常用
for足够:小于 13 的整数,原生 int 安全;13–17 可用 float 临时顶一顶(但别用于金融计算) - 真要算 100!,必须用 BCMath 或 GMP;GMP 更快,但需扩展启用,
gmp_strval(gmp_fact($n))是最简方案 - 别用
array_product(range(1, $n))——创建数组开销大,$n大时内存爆炸,还慢
真正麻烦的从来不是“怎么写”,而是“谁来保证输入合法、精度够用、不悄悄溢出”。尤其是嵌入到表单处理或 API 中时,阶乘这种看似简单的操作,最容易因一个负数或空字符串让整个流程静默失败。











