biginteger不能用+或==,因它是不可变引用类型:+无法重载且编译报错,==比较地址而非值;应使用add()等方法及compareto()/equals()比较数值。

BigInteger 为什么不能直接用 + 或 ==
因为 BigInteger 是不可变对象,不是基本类型。所有运算都返回新实例,+ 这种操作符根本不能重载,Java 里直接写 a + b 会编译报错;而 == 比较的是引用地址,不是数值相等。
实操建议:
- 改用
add()、multiply()、subtract()等方法 —— 它们返回新的BigInteger实例 - 数值比较必须用
compareTo()(返回 -1/0/1)或equals()(注意:equals()可用,但==绝对不行) - 从字符串构造更安全:
new BigInteger("999999999999999999999999999999");用long构造时容易因截断出错
什么时候该用 BigInteger 而不是 long 或 BigDecimal
long 最大值是 9223372036854775807(约 9.2×10¹⁸),超了就溢出且无声 —— 运算结果完全错误但不报错;BigDecimal 带小数精度,做纯整数运算反而引入不必要的标度和舍入逻辑。
典型适用场景:
立即学习“Java免费学习笔记(深入)”;
- 密码学计算(如 RSA 中的模幂:
modPow()) - 天文/金融中确定无误差的大整数累加(比如链上 token 总量统计)
- 算法题里明确要求“结果可能很大”,且只要整数部分
- 避免用
BigDecimal替代:它内部用BigInteger存整数部分,但多一层封装,性能低、API 更啰嗦
常见构造错误和 toString() 的坑
最常踩的两个点:一是误用 BigInteger.valueOf(long) 处理已溢出的字面量;二是调用 toString() 后再解析,却忘了默认是十进制,而某些场景需要十六进制输出(比如哈希摘要)。
实操建议:
- 别写
BigInteger.valueOf(10000000000000000000L)—— 这个字面量在编译期就被截断成负数,构造出的BigInteger是错的 - 要输出十六进制,用
toString(16),不是toHexString()(后者是Integer的静态方法,不适用于BigInteger) - 从二进制字符串构造?用
new BigInteger("101010", 2),第二个参数指定进制,不传默认是 10 - 空字符串或只含空白会抛
NumberFormatException,校验输入前先trim()
性能敏感场景下要注意的方法选择
BigInteger 所有操作都是 O(n) 或更高复杂度(n 是位数),远慢于 long。但有些方法差异很大:比如 pow(int) 对小指数很快,但 modPow() 内部用快速幂+蒙哥马利约减,比手动循环取模快几个数量级。
关键取舍点:
- 判断奇偶别用
mod(BigInteger.TWO).equals(BigInteger.ZERO),直接用testBit(0)—— 快一个数量级 - 除法慎用
divide():它要求整除,否则抛ArithmeticException;需要商余分离时,用divideAndRemainder()一次算两个 - 大量连续加法?别链式调用
a.add(b).add(c).add(d),JVM 不会优化,老老实实拆成变量暂存,减少临时对象 - 如果只是做大小比较且数字通常不超
long,先尝试longValueExact(),成功就走原生路径,失败再 fallback 到compareTo()
真正麻烦的不是语法,而是意识不到「它不是数字,它是一段不可变的、带符号的、任意长度的二进制数据」——所有方法都在操作这个结构,而不是“算术”本身。










