为什么 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
为什么 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