почему bigInteger не имеет длины в битах для -1? - PullRequest
2 голосов
/ 30 сентября 2019

почему BigInteger.bitLength() печатает 0 для -1 в Java:

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

в исходном коде для BigInteger есть комментарий:

bitLength еще не инициализировано

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
            }

Ответы [ 2 ]

3 голосов
/ 30 сентября 2019

Проверьте документацию для метода BigInteger.bitLength():

Возвращает количество бит в минимальном представлении двоичного числа этого BigInteger, , исключая знак бит. [...]

Вам нужны нулевые биты "значения" для представления значения 0. По сути, вам «ничего не нужно делать», и у вас есть значение 0. С помощью знакового бита вы можете переключаться между 0 и -1 (аналогично дополнению до двух).

Если у вас есть значение 1, вам нужен один бит «значения», поэтому BigInteger.bitLength() вернет 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
3 голосов
/ 30 сентября 2019

Возвращает минимальное дополняющее два (1), исключая знаковый бит, что в данном случае равно 0. Двоичное значение -1 равно 0xFFFF... / 0b1111..., с дополнением к одному (max - value), равным 0, которое добавляет к 1, чтобы стать дополнением к двум (дополнение к одному + 1).

Однако переменная n из #bitLength - это не значение вашего BigInteger, а значение сохраненного поля bitLength минус 1 (а 0 означает, что оно еще не рассчитано). Таким образом, BigInteger со значением -1, возвращающим 0 из #bitLength, является совпадением по отношению к ним, использующим -1 в качестве часового значения.

Они используют это значение для обозначения того, что поле еще не было лениво инициализировано , а затем для поля bitLength установлено правильное значение (0). Помните, что BigInteger является неизменным, поэтому при вычислении bitLength он никогда не изменится для этого экземпляра.

...