为什么 bigInteger 没有 -1 的位长?

why bigInteger doesn't have bit length for -1?

为什么 BigInteger.bitLength() 在 Java 中为 -1 打印 0:

System.out.println(BigInteger.valueOf(-1).bitLength());

BigInteger 的源代码中有一条注释说:

bitLength not initialized yet

public int bitLength() {
        int n = bitLengthPlusOne - 1;
        if (n == -1) { // bitLength not initialized yet
            int[] m = mag;
            int len = m.length;
            if (len == 0) {
                n = 0; // offset by one to initialize
            }

它 returns 最小 two's-complement (1),不包括符号位,在这种情况下为 0。 -1的二进制值为0xFFFF.../0b1111...,补码(max - value)变为0,与1相加成为补码(one's补码 + 1).

但是,#bitLength 中的 n 变量不是您的 BigInteger 的值,而是存储的 bitLength 字段的值减去 1(而 0 表示它不是尚未计算)。因此,BigInteger 的值为 -1#bitLength 返回 0 与使用 -1 作为标记值的它们是巧合。

他们使用此值表示该字段尚未 lazily initialized,然后将 bitLength 字段设置为正确的值 (0)。请记住,BigInteger 是不可变的,因此在计算 bitLength 时,它永远不会因该实例而改变。

查看 BigInteger.bitLength() 方法的文档:

Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit. [...]

您需要零 "value" 位来表示值 0。基本上,您 "don't need to do anything" 并且您拥有价值 0。使用符号位,您可以在 0-1 之间切换(类似于补码)。

当你有值 1 时你需要一个 "value" 位,所以 BigInteger.bitLength() 将 return 1 用于 BigInteger 值 1.检查以下 for 循环及其生成的输出:

for (int i=-16; i<=16; i++) {
    BigInteger x = BigInteger.valueOf(i);
    System.out.println(x+"| bitlength: "+x.bitLength());    
}

输出为:

-16| bitlength: 4
-15| bitlength: 4
-14| bitlength: 4
-13| bitlength: 4
-12| bitlength: 4
-11| bitlength: 4
-10| bitlength: 4
-9| bitlength: 4
-8| bitlength: 3
-7| bitlength: 3
-6| bitlength: 3
-5| bitlength: 3
-4| bitlength: 2
-3| bitlength: 2
-2| bitlength: 1
-1| bitlength: 0
0| bitlength: 0  /* 0b */
1| bitlength: 1  /* 0b1 */
2| bitlength: 2
3| bitlength: 2  /* 0b11 */
4| bitlength: 3
5| bitlength: 3
6| bitlength: 3
7| bitlength: 3  /* 0b111 */
8| bitlength: 4
9| bitlength: 4
10| bitlength: 4
11| bitlength: 4
12| bitlength: 4
13| bitlength: 4
14| bitlength: 4
15| bitlength: 4 /* 0b1111 */
16| bitlength: 5