在 Java 开发里,int 和 long 虽然够快,但它们都有明确的取值上限。一旦数值超过范围,程序通常不会主动提醒,结果却已经发生溢出,排查时往往只能从异常业务结果倒推问题。
如果场景涉及超大整数、精确整数运算、进制处理,或者算法题中的高精度计算,就需要用到 java.math 包下的 BigInteger。下面按“为什么要用、怎么创建、怎么运算、哪些地方最容易写错”的顺序,把这套用法一次讲清楚。
为什么需要 BigInteger
int、long 等基本整数类型都只能表示固定范围内的数值。超过上限后,结果会直接溢出,而且这种错误往往是静默发生的,不会在编译或运行时自动提示。
这也是 BigInteger 存在的意义:它专门用于处理任意长度的整数,理论上只受 JVM 内存限制,适合以下几类场景:
- 算法竞赛中的高精度整数运算
- 金融统计里的大整数累计
- 密码学、大数加密相关计算
- 需要幂运算、取模、素数判断、进制转换的程序
BigInteger 的核心特点
在正式写代码前,先要明确 BigInteger 和基本类型的几个本质区别。
- 支持超大整数:没有固定数值上限,主要受内存限制。
- 不可变类:每次运算都会返回新的
BigInteger对象,原对象本身不会被修改。 - 不能直接用运算符:不支持
+ - * / %,必须调用对应方法。 - 整数精度无损:只要是整数运算,就不会出现精度丢失问题。
- 性能弱于基本类型:底层处理成本更高,不适合高频、小数值的普通计算。
BigInteger 如何创建
BigInteger 没有无参构造,实际开发里常见的创建方式主要有 4 种。

通过普通数值创建
适合仍然处在 long 范围内的数值,写法也最直接。
// 通过 long 数值创建(适合 long 范围内数值)
BigInteger num1 = BigInteger.valueOf(123456);
// 负数创建
BigInteger num2 = BigInteger.valueOf(-98765);
通过字符串创建超大整数
这是最常用、也最推荐的方式,尤其在数值已经超过 long 上限时,字符串构造几乎是唯一可靠选择。
// 远超 long 最大值的超大整数
BigInteger bigNum = new BigInteger("999999999999999999999999999999");
按指定进制创建
如果原始数据本身就是二进制、十六进制等字符串,可以在构造时直接声明进制。
// 将二进制 1010 转为十进制数字
BigInteger binaryNum = new BigInteger("1010", 2);
// 将十六进制转为十进制
BigInteger hexNum = new BigInteger("FF", 16);
直接使用系统常量
一些常见值已经有内置常量,没必要重复创建对象。
BigInteger.ZERO; // 0
BigInteger.ONE; // 1
BigInteger.TWO; // 2
BigInteger.TEN; // 10
常用算术运算怎么写
使用 BigInteger 时,最重要的一条规则就是:所有运算都会返回新对象,原对象不变。如果不接收返回值,这次运算等于没有生效。
BigInteger a = new BigInteger("100000000000000000000");
BigInteger b = new BigInteger("200000000000000000000");
// 1. 加法
BigInteger addRes = a.add(b);
// 2. 减法
BigInteger subRes = a.subtract(b);
// 3. 乘法
BigInteger mulRes = a.multiply(b);
// 4. 除法(整除,只取整数部分)
BigInteger divRes = b.divide(a);
// 5. 取模
BigInteger modRes = b.mod(a);
// 6. 求绝对值
BigInteger absRes = subRes.abs();
// 7. 取反
BigInteger negRes = a.negate();
// 8. 幂运算
BigInteger powRes = a.pow(3);
// 9. 最大/最小值
BigInteger maxRes = a.max(b);
BigInteger minRes = a.min(b);
如果只是做整除,divide() 就够用;如果还需要余数,下一节的 divideAndRemainder() 会更高效。
如何同时拿到商和余数
普通的 divide 只会返回商。在算法题、取模计算、分段处理等场景里,更常见的是一次同时拿到商和余数,这时可以用 divideAndRemainder。
BigInteger num = new BigInteger("100");
BigInteger divisor = new BigInteger("3");
// 数组:[0]商,[1]余数
BigInteger[] res = num.divideAndRemainder(divisor);
System.out.println("商:" + res[0]);
System.out.println("余数:" + res[1]);
返回值是一个数组,其中 res[0] 是商,res[1] 是余数。
BigInteger 该怎么比较大小
BigInteger 是对象,不是基本类型,因此不能用 >、<、== 直接比较数值大小或内容。

BigInteger x = new BigInteger("888");
BigInteger y = new BigInteger("666");
// compareTo:大于返回1,等于返回0,小于返回-1
int cmp = x.compareTo(y);
// 判断是否相等(推荐,杜绝 == 地址比较坑)
boolean eq = x.equals(y);
// 判断正负、零
boolean zero = x.equals(BigInteger.ZERO);
boolean positive = x.compareTo(BigInteger.ZERO) > 0;
boolean negative = x.compareTo(BigInteger.ZERO) < 0;
常见判断规则可以直接记成两条:
- 比较大小用
compareTo() - 比较数值是否相等用
equals()
进制转换与类型转换
BigInteger 不只是做大数运算,也经常承担进制转换和类型转换的角色。
转为不同进制字符串
BigInteger num = new BigInteger("255");
String binary = num.toString(2); // 转二进制
String oct = num.toString(8); // 转八进制
String hex = num.toString(16); // 转十六进制
转回基本类型时要注意范围
把大整数转成 long、int 时,最关键的问题是范围是否安全。原文提示“超出基本类型范围会抛异常”,实际编写这类代码时,最好先做范围判断,再决定是否转换。
// 转 long(范围溢出抛异常)
long longVal = num.longValue();
// 转 int
int intVal = num.intValue();
// 精准判断是否可以转为 long
boolean canLong = num.bitLength() <= 63;
位运算与常用工具方法
在算法和底层计算场景里,BigInteger 还提供了一整套位运算和工具方法。
BigInteger n = new BigInteger("10");
n.and(BigInteger.ONE); // 与运算
n.or(BigInteger.ZERO); // 或运算
n.xor(BigInteger.TWO); // 异或运算
n.not(); // 取反
n.shiftLeft(2); // 左移(乘2^2)
n.shiftRight(1); // 右移(除2)
// 获取二进制位数
int bitLen = n.bitLength();
// 判断是否为素数
boolean prime = n.isProbablePrime(50); // 参数为置信度
其中比较常见的几个用途包括:
bitLength():判断位数或辅助判断是否可安全转为基本类型shiftLeft()、shiftRight():做高效的位移计算isProbablePrime(50):快速进行素数判断
最容易踩坑的 4 个地方
1. 忘记接收返回值
BigInteger 是不可变类,调用方法不会直接改掉原变量。
// 错误写法
BigInteger a = BigInteger.TEN;
a.add(BigInteger.TEN);
System.out.println(a); // 仍然是10
// 正确写法
a = a.add(BigInteger.TEN);
2. 用 == 比较数值
== 比较的是对象地址,equals() 比较的是数值内容;涉及大小判断时,则应使用 compareTo()。
3. 把它当成基本类型写运算符
BigInteger 不支持 + - * / 这类运算符,必须改用 add()、subtract()、multiply()、divide() 等方法。
4. 超大数还想用 valueOf
只要数值已经超出 long 范围,就不能再通过 valueOf() 或字面量直接处理,应该改用字符串构造。
什么时候该用 BigInteger,什么时候不该用
选型时可以直接按场景判断:

- 普通整数,范围明确在 long 内:优先使用
long,性能更高。 - 数值已经超过 long 范围:必须使用
BigInteger。 - 高频循环、性能敏感场景:尽量继续使用基本类型,避免不必要的大数对象开销。
- 算法题、大数加密、进制运算、素数判断:优先考虑
BigInteger。
一句话概括就是:BigInteger 解决的是“算得对”的问题,基本类型更擅长“算得快”的问题。













