在Java编程中,阶乘计算是很多基础算法题和数学相关功能的常见需求,不少开发者会直接使用long类型来存储计算结果,但往往会遇到结果异常的情况,这大多是因为long类型溢出的问题。

long类型的数值范围与溢出原因
Java中的long是64位有符号整数,其取值范围是-9223372036854775808到9223372036854775807。阶乘的数值增长非常快,比如20的阶乘结果是2432902008176640000,还在long的范围内,但21的阶乘结果是51090942171709440000,已经超出了long的最大值,此时用long存储就会出现溢出,结果会变成负数或者错误的数值。
我们可以通过一段简单的代码验证long溢出的情况:
public class LongFactorialTest {
public static void main(String[] args) {
long result = 1;
// 计算21的阶乘
for (int i = 1; i <= 21; i++) {
result *= i;
}
// 输出结果,此时已经溢出
System.out.println("21的阶乘(long计算):" + result);
// 输出long的最大值对比
System.out.println("long最大值:" + Long.MAX_VALUE);
}
}运行上述代码会发现,21的阶乘计算结果是一个负数,这就是典型的溢出表现。
BigInteger的基本特性
BigInteger是Java中用于处理任意精度整数的类,位于java.math包下,它的大小只受内存限制,不会出现数值溢出的问题,非常适合处理大数阶乘这类场景。
和long不同,BigInteger是不可变类,所有的运算都会返回一个新的BigInteger对象,常用的运算方法包括:
add(BigInteger val):加法运算multiply(BigInteger val):乘法运算valueOf(long val):将long类型转换为BigInteger
用BigInteger实现大数阶乘计算
使用BigInteger计算阶乘的逻辑和用long类似,只是需要将数值都转换为BigInteger类型,并且使用对应的乘法方法。
下面是完整的大数阶乘计算代码示例:
import java.math.BigInteger;
public class BigIntegerFactorialTest {
public static void main(String[] args) {
int num = 21;
// 初始化结果为BigInteger的1
BigInteger result = BigInteger.valueOf(1);
for (int i = 1; i <= num; i++) {
// 将i转换为BigInteger后做乘法
result = result.multiply(BigInteger.valueOf(i));
}
System.out.println(num + "的阶乘(BigInteger计算):" + result);
// 可以计算更大的数,比如100的阶乘
int bigNum = 100;
BigInteger bigResult = BigInteger.valueOf(1);
for (int i = 1; i <= bigNum; i++) {
bigResult = bigResult.multiply(BigInteger.valueOf(i));
}
System.out.println(bigNum + "的阶乘长度:" + bigResult.toString().length() + "位");
}
}运行上述代码,21的阶乘会输出正确的数值,100的阶乘也可以正常计算,不会出现溢出问题。
两种方式对比与场景选择
我们可以通过下面的表格对比两种方式的差异:
| 对比项 | long类型 | BigInteger类型 |
|---|---|---|
| 数值范围 | 固定64位,最大约9e18 | 任意精度,仅受内存限制 |
| 运算性能 | 高,基本类型运算速度快 | 较低,对象操作开销更大 |
| 适用场景 | 阶乘数值小于21的场景 | 大数阶乘、任意精度整数运算场景 |
如果确定阶乘的数值不会超过20,用long类型计算效率更高;如果不确定数值大小或者需要计算更大的阶乘,优先选择BigInteger避免溢出问题。
注意事项
使用BigInteger时需要注意,不要频繁创建不必要的对象,比如在循环中尽量复用已有的BigInteger对象。另外,BigInteger的运算结果都是新对象,赋值的时候需要接收返回值,否则运算不会生效。
如果需要在html页面中展示大数阶乘的结果,直接将BigInteger转换为字符串即可,不需要额外处理数值格式问题。
实际开发中遇到整数运算时,先预估数值的范围,再选择合适的数值类型,能有效避免很多隐蔽的溢出bug。
Java大数阶乘long溢出BigInteger阶乘计算修改时间:2026-06-02 04:37:49