You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归阶乘算法计算46342!时结果异常,求故障原因

问题根源:int类型溢出导致RecursiveCounter计算失效

你碰到的这个问题其实是个典型的整数溢出坑,咱们对着RecursiveCounter的代码就能把原因说透:

核心问题代码

看RecursiveCounter里处理小区间的逻辑:

// 左侧区间处理
if (middle - from > 1) 
    left = count(from, middle); 
else 
    left = new BigInteger(String.valueOf(from * middle));

// 右侧区间处理
if (to - (middle + 1) > 1) 
    right = count(middle + 1, to); 
else 
    right = to == middle + 1 ? new BigInteger(String.valueOf(to)) : new BigInteger(String.valueOf((middle + 1) * to));

这里的from * middle和(middle + 1) * to是用int类型直接做乘法的,但Java里int的取值范围是-2^31到2^31-1(也就是-2147483648到2147483647)。咱们算个简单的数:√2147483647 ≈ 46340.95,也就是说只要两个大于等于46341的整数相乘,结果就会超过int的最大值,触发有符号整数溢出——溢出后数值会变成一个错误的负数或乱码值,再转成BigInteger自然就彻底错了。

当你计算46342!时,递归拆分到某个小区间(比如from=46341、middle=46342),from * middle的乘积直接突破int上限,溢出后得到错误值,这就导致整个递归分支的结果出错,最终的阶乘结果自然不对。

为什么其他计数器没问题?

  • LoopCounter:每次都是把单个int转成BigInteger再相乘(result.multiply(new BigInteger(String.valueOf(i)))),从来不会直接做两个int的乘法,完全避开了溢出风险。
  • ParallelCounter:当拆分到阈值以下时,调用的是LoopCounter的顺序计算逻辑,同样是单个int转BigInteger相乘,所以也不会触发溢出。

修复方案

把RecursiveCounter里直接做int乘法的地方,改成用BigInteger来计算:

// 左侧修改后
left = BigInteger.valueOf(from).multiply(BigInteger.valueOf(middle));

// 右侧修改后
right = BigInteger.valueOf(middle + 1).multiply(BigInteger.valueOf(to));

这样就彻底避免了int溢出的问题,不管计算多大的阶乘,小区间的乘积都会用BigInteger正确计算。

内容的提问来源于stack exchange,提问作者Leonid Bor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:11:17