阶乘计算应优先用迭代而非递归;php默认递归深度限制易触发错误,迭代更稳定;大数阶乘需用bcmath扩展保证精度,且须先检查extension_loaded('bcmath')。

阶乘计算用递归还是循环?PHP里别乱选
PHP 小程序后端算阶乘,function factorial($n) 写成递归看着简洁,但小程序请求并发稍高或 $n 超过 100 就容易触发 Maximum function nesting level of '256' reached 错误。递归在 PHP 默认配置下非常脆弱,尤其微信/支付宝小程序后端常跑在共享环境,xdebug.max_nesting_level 往往没调高。
更稳妥的做法是用迭代:
function factorial($n) {
if (!is_int($n) || $n < 0) {
throw new InvalidArgumentException('阶乘只支持非负整数');
}
$result = 1;
for ($i = 2; $i <= $n; $i++) {
$result *= $i;
}
return $result;
}
-
$n === 0或$n === 1时直接返回1,循环从2开始,避免冗余判断 - 务必校验输入:小程序前端传来的
n可能是字符串"5"或空值,is_int()会失败,建议加filter_var($n, FILTER_VALIDATE_INT)预处理 - 超过
PHP_INT_MAX(通常 2^63-1)后,整数会自动转为float,精度丢失。若需大数(如 1000!),必须用bcmul()+ 字符串实现
小程序 POST 过来的是字符串,PHP 接口不校验就崩
微信小程序用 wx.request({ method: 'POST', data: { n: 5 } }) 发请求,PHP 后端收到的 $_POST['n'] 是字符串 "5",不是整数。直接喂给 factorial() 函数,for 循环里的 $i 会隐式转换,但一旦传入 <code>"abc" 或空字符串,$n 变成 0,结果恒为 1,错误静默发生。
接口入口必须做类型清洗:
立即学习“PHP免费学习笔记(深入)”;
$n = $_POST['n'] ?? null;
if ($n === null || !is_numeric($n) || (int)$n != $n || $n < 0) {
http_response_code(400);
echo json_encode(['error' => '参数 n 必须是非负整数']);
exit;
}
$n = (int)$n;
- 用
(int)$n != $n排除"5.0"或"1e2"这类数值字符串 - 别用
intval()——它对"99999999999999999999"这种超长数字会截断成PHP_INT_MAX - 小程序端最好也加 JS 校验:
Number.isInteger(Number(n)) && n >= 0
返回 JSON 时注意中文和 Content-Type
PHP 默认输出是 text/html,小程序 JSON.parse() 遇到 HTML 头或乱码直接报错 SyntaxError: Unexpected token 。常见原因有:BOM 头、echo 前有空格、没设 header。
标准响应写法:
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'n' => $n,
'result' => factorial($n),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
-
JSON_UNESCAPED_UNICODE防止中文变\u4f60,小程序显示正常 - 文件保存为 UTF-8 无 BOM 格式,编辑器里关掉「UTF-8 with BOM」选项
- 确保整个 PHP 文件顶部没空行、没空格、没注释——任何输出都会破坏 JSON 结构
大数阶乘(n > 20)怎么不溢出?别硬刚 int
21! 已超 PHP_INT_MAX(约 9.2e18),PHP 自动转 float,但 float 只有 15~17 位有效数字,50! 之后误差巨大。小程序若要展示精确值(比如数学题答案),必须用 BCMath 扩展。
启用前先确认扩展已加载:extension_loaded('bcmath'),否则 bcmul() 直接报致命错误。
function factorial_big($n) {
if ($n < 2) return '1';
$result = '1';
for ($i = 2; $i <= $n; $i++) {
$result = bcmul($result, (string)$i, 0);
}
return $result;
}
- 所有操作数必须是字符串,
bcmul('123', 456)会失败,得写bcmul('123', '456') - 第三个参数
scale设为0表示不保留小数位,避免末尾多出.000 - 微信小程序
JSON.stringify()对超长数字字符串无压力,放心传
真正麻烦的是调试:var_dump() 显示 string(100) "..." 看不到全貌,用 echo substr($result, 0, 50) . '...'; 截取前 50 位快速验证逻辑是否走通。











