powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / почему BitSet использует long[] размера 6
25 сообщений из 26, страница 1 из 2
почему BitSet использует long[] размера 6
    #39391093
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Стыдно, но не могу вспомнить теорию, позволяющую понять

почему BitSet-у достаточно шести лонгов, чтобы хранить массив размера 2^31-1 битов.

судя по тому, что
2 бита позволяют закодировать 4 разных числа
3 бита - 8, то
(2^31)-1 битов, то нам нужно число диапазона 2^((2^31)-1 ).

Как это вяжется с шестью 64 битными лонгами - не понимаю.

ну или пойти с другой стороны:

лонг это 64 бита, 6 лонгов это 64*8 битов.

это ведь всяко много меньше (2^31)-1

Объясните пожалуйста
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391114
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerпочему BitSet-у достаточно шести лонгов, чтобы хранить массив размера 2^31-1 битов.

Подтверждено эксперементально?

questionerлонг это 64 бита, 6 лонгов это 64*8 битов.

Что-то с арифметикой тут тоже не так.
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391281
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczПодтверждено эксперементально?
Наверно человек так понял
java.util.BitSet/*
* BitSets are packed into arrays of "words." Currently a word is
* a long, which consists of 64 bits, requiring 6 address bits.
* The choice of word size is determined purely by performance concerns.
*/
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391285
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей АрсеньевBlazkowiczПодтверждено эксперементально?
Наверно человек так понял
java.util.BitSet/*
* BitSets are packed into arrays of "words." Currently a word is
* a long, which consists of 64 bits, requiring 6 address bits.
* The choice of word size is determined purely by performance concerns.
*/


Да, вы правы,а как это правильно истолковать?


Blazkowicz Что-то с арифметикой тут тоже не так.

Очепятка 64*6 конечно
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391300
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Ну примерно так.
Хранится в массиве long[]
Для того чтобы узнать в каком по счету long хранится бит
делается следующая операция
Код: java
1.
2.
3.
 private static int  wordIndex(int bitIndex) {
         return bitIndex >> ADDRESS_BITS_PER_WORD;
     }


Собственно установка бита делается (если упростить для понимания, откинув всякие expand)
Код: java
1.
words[wordIndex(bitIndex)] |= (1L << bitIndex);
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391328
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньевquestioner,


Собственно установка бита делается (если упростить для понимания, откинув всякие expand)
Код: java
1.
words[wordIndex(bitIndex)] |= (1L << bitIndex);



|=

а что за операция такая?

long h |= (1L << 2);

так например нельзя написать
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391330
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391334
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

для |= надо иметь предыдущее значение.
это эквивалент h = h |
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391337
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньевquestioner,

для |= надо иметь предыдущее значение.
это эквивалент h = h |

аа понятно это OR

Теперь по поводу выбора нужного long.


Почему смещение именно на 6 ?
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391339
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

2^6=?
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391368
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

long это "слово" в реализации BitSet его размер 64 бита
Чтобы получить бит по индексу надо произвести две операции
1. Получить индекс long-а в массиве
2. Получить индекс бит-а внутри long-а

индекс long-а это индекс бита делённый на 64
64 = 2^6
деление на 64 эквивалентно сдвигу на 6 позиций
вот и выходит
индекс long-а это индекс бита >> 6

Код: java
1.
2.
3.
private static int wordIndex(int bitIndex) {
        return bitIndex >> ADDRESS_BITS_PER_WORD;
}



Индекс бита внутри лонга это остаток от деления индекса бита на 64. Но нам особо не нужен, так как long это не массив - по индексу не адресуешь.

Для того чтобы проверить или установить значение бита нужно наложить маску на этот бит. Для получения маски берём единицу 1L и сдвигаем влево на нужную позицию. Сдвиг цикличный, поэтому не паримся на счет границ.
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391437
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

Спасибо, разжевали.


Один момент только не уловил:

Код: java
1.
1L << bitIndex




пуска у нас индекс попал в первый лонг (он же нулевой)

и пусть это будет 20(аргумент метода set).

1 это же

0...[63 штуки]1

1<<20

это ведь будет 0...[39 штук] 10...[20 штук]

и получится, что мы установили 40 бит вместо 20
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391444
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
или они с конца пронумерованы?
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391446
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Код: java
1.
2.
3.
4.
5.
        System.out.println(Long.toBinaryString(1L));
        System.out.println(Long.toBinaryString(1L << 20));

1
100000000000000000000
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391447
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner1<<20
это ведь будет 0...[39 штук] 10...[20 штук]
и получится, что мы установили 40 бит вместо 20

Какая разница? Число никто не видит. А get так же сработает.
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391448
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerили они с конца пронумерованы?
А есть принципиальная разница?
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391450
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczquestionerили они с конца пронумерованы?
А есть принципиальная разница?


это объясняет почему используется сдвиг единицы влево. Для клиента класса разницы никакой.
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391454
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Я прогнал. Сдвиг в Java не цикличиный. Просто при сдвиге не используются значения дальше размера типа. Для сдвига int только 5 бит, а для сдвига long только 6.
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391459
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczquestioner,

Я прогнал. Сдвиг в Java не цикличиный. Просто при сдвиге не используются значения дальше размера типа. Для сдвига int только 5 бит, а для сдвига long только 6.

а что подразумевается под размером типа?(а то у меня в голове цифры 32 и 64 бита соответственно)

допустим прилетоло нам число 70.

мы выяснили, что оно во втором long

дальше идёт операция 1L<< 70

Код: java
1.
2.
System.out.println(1L<< 70);
1000000



похож прям на цикличный
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391543
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Почитай определение операции сдвига в JLS.
Размер int - 32 = 2^5 бита. То есть 5 бит достаточно чтобы адресовать номер бита в int. Поэтому для сдвига используется только 5 бит от значения указывающее на количество сдвигов.
То есть 1L << 70 эквивалентно 1L << 6, потому что 64 это уже 7й бит в значении 70. Он не используется. Для long используется только 6 бит от числа справа (70).
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391679
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

Подтверждается тем, что

Код: java
1.
2.
3.
4.
5.
   
        System.out.println(1L << 127);
        System.out.println(1L << 191);
        System.out.println(1L << 255);
        System.out.println(1L << 511);



возвращает одно и то же
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391851
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerили они с конца пронумерованы?
YouTube Video
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391862
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerПодтверждается тем, что
...
возвращает одно и то же
Правильно. JLS нам не указ. Эксперимент - наше всё.
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391881
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczquestionerПодтверждается тем, что
...
возвращает одно и то же
Правильно. JLS нам не указ. Эксперимент - наше всё.

Нельзя же никому на слово верить)))
...
Рейтинг: 0 / 0
почему BitSet использует long[] размера 6
    #39391896
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerпохож прям на цикличный
Похож но не ёж.
Другими словами в качестве аргумента для количества бит на которые сдвигать неявным образом используется остаток от деления на максимальную размерность того числа которое указано.
Другими словами сдвиг на 33 бита это тоже самое что сдвиг на 1.

При циклическом сдвиге влево справа вылезает левый бит. При не циклическом, заранее установленный (0 или например знак отрицательного числа, если двигаем вправо).

на примере int
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
  System.out.println("10000000000000010000000000000001<<1  :"+Integer.toBinaryString(0x80010001<<1));
  System.out.println("1<<31                                :"+Integer.toBinaryString(1<<31));
  System.out.println("1<<32                                :"+Integer.toBinaryString(1<<32));
  System.out.println("10000000000000010000000000000001>>1  :"+Integer.toBinaryString(0x80010001>>1));
  System.out.println("10000000000000010000000000000001>>>1 :"+Integer.toBinaryString(0x80010001>>>1));
  System.out.println("10000000000000000000000000000001>>31 :"+Integer.toBinaryString(0x80000001>>31));
  System.out.println("10000000000000000000000000000001>>>31:"+Integer.toBinaryString(0x80000001>>>31));
  System.out.println("10000000000000000000000000000001>>32 :"+Integer.toBinaryString(0x80000001>>32));
  System.out.println("10000000000000000000000000000001>>>32:"+Integer.toBinaryString(0x80000001>>>32));

...
Рейтинг: 0 / 0
25 сообщений из 26, страница 1 из 2
Форумы / Java [игнор отключен] [закрыт для гостей] / почему BitSet использует long[] размера 6
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]