BigInteger.shiftLeft(n)逻辑左移n位等价于×2ⁿ,shiftRight(n)逻辑右移n位等价于向零取整的÷2ⁿ,二者均不溢出、n≥0,性能优于乘除幂运算。

BigInteger.shiftLeft(n) 和 BigInteger.shiftRight(n) 是 Java 中对大整数进行逻辑左移和逻辑右移的高效位运算方法,它们不改变符号,只对数值的二进制表示做移位,相当于乘以或除以 2 的幂(但支持任意大的整数)。
shiftLeft(n):等价于 × 2ⁿ
将当前 BigInteger 的二进制表示向左移动 n 位,低位补 0。
数学上等价于:this.multiply(BigInteger.valueOf(2).pow(n)),但性能更好(底层直接操作二进制位)。
-
n必须 ≥ 0,否则抛ArithmeticException - 负数也按绝对值的二进制形式移位(符号位不参与,是逻辑移位)
BigInteger a = new BigInteger("5"); // 二进制: 101
BigInteger b = a.shiftLeft(2); // → 10100 = 20
System.out.println(b); // 输出: 20shiftRight(n):等价于 ÷ 2ⁿ(向零取整)
将当前 BigInteger 的二进制表示向右移动 n 位,高位补符号位?不 —— shiftRight 是逻辑右移(不是算术右移),对正数补 0,对负数也补 0(注意:这和 int/long 的 >> 不同!)。
⚠️ 关键点:
-
BigInteger.shiftRight(n)始终执行无符号右移(即等价于(this.abs().shiftRight(n)).multiply(signum)?不对!实际是:先转为二进制绝对值,右移后根据原符号决定结果符号) - 更准确说:它等价于
this.divide(BigInteger.valueOf(2).pow(n)),即向零截断的整除(floor division 对负数不成立,而是 truncating division)
BigInteger a = new BigInteger("13"); // 13 / 4 = 3.25 → 截断为 3
System.out.println(a.shiftRight(2)); // 输出: 3
BigInteger b = new BigInteger("-13"); // -13 / 4 = -3.25 → 截断为 -3
System.out.println(b.shiftRight(2)); // 输出: -3✅ 所以 shiftRight(n) 的行为就是:floor(this / 2ⁿ) 对非负数成立;对负数,是向零取整(即 Math.floorDiv(this, pow(2,n)))。
立即学习“Java免费学习笔记(深入)”;
和普通 int/long 移位的区别
| 特性 |
int >> n(算术右移) |
BigInteger.shiftRight(n) |
|---|---|---|
| 负数右移 | 高位补 1(保持符号) | 高位补 0(逻辑移位),但结果仍带原符号,效果等价于整除 |
| 溢出 | 会溢出(模 2³² 或 2⁶⁴) | 无溢出,精度完整 |
| 支持负 n | 不允许(编译报错) |
n < 0 直接抛 ArithmeticException
|
实用建议
- 用
shiftLeft(n)替代multiply(pow(2,n)),更简洁高效 - 用
shiftRight(n)替代divide(pow(2,n)),避免构造临时BigInteger - 需要算术右移(保留符号扩展)?
BigInteger没有直接提供,但通常不需要——因为它的值范围无限,符号由signum()单独管理 - 移位量
n很大也没问题(比如shiftLeft(1000000)),内部用数组分段处理
// 安全写法:确保 n >= 0
int n = 10;
BigInteger x = ...;
if (n >= 0) {
BigInteger y = x.shiftLeft(n);
}


















