Представьте 10000 логических значений, используя только 10000 бит

Я хочу представить 10000 бит информации (каждый может быть либо единицей, либо нулем). Есть ли способ сделать это?

Википедия объясняет небольшой хак для достижения этой цели. Но затем он просит меня указать число, равное 2^10000, для хранения 10000 бит.

Есть ли какой-нибудь способ, который можно использовать даже для хранения большого количества битов?


person Nikunj Banka    schedule 18.03.2013    source источник
comment
Вы не можете запрашивать детали реализации и указывать язык-независимо.   -  person harold    schedule 18.03.2013
comment
Целое число на 32-битной машине, используемое в качестве битового поля, может содержать 32 бита. Таким образом, массив из 32 целых чисел может содержать 1024 бита...   -  person antlersoft    schedule 18.03.2013
comment
@harold Я в основном прошу алгоритм. И этот алгоритм не должен использовать никаких языковых конструкций.   -  person Nikunj Banka    schedule 18.03.2013
comment
Или, если вы посмотрите на байты (подумайте о массиве, списке и т. д.), вам нужно 1250 байт для хранения 10000 бит.   -  person tink    schedule 18.03.2013
comment
@antlersoft сам массив из 32 целых чисел использует 32 * 4 * 8 бит.   -  person Nikunj Banka    schedule 18.03.2013
comment
Похоже, вам просто нужен обычный BigInteger   -  person leppie    schedule 18.03.2013
comment
возможный дубликат C hack для хранения бита, который занимает 1 бит?   -  person KevinDTimm    schedule 18.03.2013
comment
На самом деле это не вопрос, не зависящий от языка. В некоторых языках вы можете просто объявить упакованный массив логических значений. В других случаях вам придется немного повозиться. Что касается того, чтобы не использовать какие-либо языковые конструкции, это на самом деле невозможно; побитовые операции с целыми числами являются единственным разумным подходом в некоторых языках, но они зависят от языка, поскольку не все языки их предоставляют.   -  person Keith Thompson    schedule 18.03.2013
comment
битовый вектор - хороший выбор для этого   -  person argentage    schedule 18.03.2013
comment
Это довольно тривиальный алгоритм, когда вы указываете язык. В C: используйте массив символов, i/8 для индекса, 1 ‹‹ (i%8) для маски. ИЛИ с маской, чтобы установить бит, И с ~(mask), чтобы очистить бит, И с маской, чтобы проверить бит. Замените 8 на количество битов в char для экзотических архитектур.   -  person Seva Alekseyev    schedule 18.03.2013
comment
@SevaAlekseyev: Используйте unsigned char, а не char, и используйте CHAR_BIT, а не 8. Конечно, это вряд ли зависит от языка.   -  person Keith Thompson    schedule 18.03.2013
comment
Теперь я удалил язык тегов, не зависящий от языка.   -  person Nikunj Banka    schedule 18.03.2013
comment
Удаление языковых агностиков на самом деле не помогает, если вы не укажете язык.   -  person Aaron Dufour    schedule 19.03.2013
comment
@Keith: Поскольку используются только сдвиги влево, нет никакой разницы между подписанным и неподписанным.   -  person Seva Alekseyev    schedule 19.03.2013
comment
@SevaAlekseyev: 1. Кто сказал, что работают только левые смены? 2. Даже при сдвигах влево некоторые сдвиги хорошо определены для левого операнда без знака и не определены для левого операнда со знаком. 3. Просто используйте unsigned char явно, и вам не нужно заботиться о том, как определяются сдвиги для подписанных аргументов.   -  person Keith Thompson    schedule 19.03.2013
comment
1. Я так и сделал :) 2. Процитируйте пожалуйста.   -  person Seva Alekseyev    schedule 19.03.2013
comment
@SevaAlekseyev: 1. Вы хотите иметь возможность хранить и извлекать указанные биты; разве для этого не нужны как левые, так и правые сдвиги? 2. N1570 6.5.7p4. 1<<7 может быть представлен в 8-битном типе без знака, но не в 8-битном типе со знаком. Побитовые операции над целыми числами со знаком: просто скажите нет.   -  person Keith Thompson    schedule 19.03.2013
comment
Нет. Смотрите мой первый комментарий. Вам просто нужен левый сдвиг, чтобы сформировать маску. Кроме того, как часто вы сталкиваетесь с реальными реализациями C, где (signed char)1‹‹7 не совпадает с (signed char)0x80?   -  person Seva Alekseyev    schedule 19.03.2013


Ответы (4)


Как объясняет Википедия, битовое поле здесь является подходящим выбором. битовое поле, которое может содержать 10 000 бит, имеет 2 ^ 10 000 состояний.

Хорошим выбором для этого (учитывая, что целые числа являются 32/64-битными) является битовый вектор, о котором спрашивают и подробно объясняют здесь:

бит-векторная реализация набора в Programming Pearls, 2nd Edition

Общая идея заключается в том, что вы используете массив целых чисел, которые используются в качестве битовых полей.

person argentage    schedule 18.03.2013
comment
Точно. Распространенным выбором является использование массива символов в качестве битового поля, но это зависит от вашей среды программирования. - person Joost; 18.03.2013

Вы можете заставить bool принимать 1 бит, например, если у вас их куча, например. в структуре, например:

struct A { bool a:1, b:1, c:1, d:1, e:1; };

Вышеупомянутый метод не будет полезен, если количество переменных велико. Поэтому вместо этого создайте массив целых чисел размером 10000/4*8. Он создаст ровно 10000 бит. Теперь вы можете получить доступ к каждому биту, используя смещение и ‹‹ или >> (например, для доступа к 55-му биту используйте пол (55/4 * 8) и >> 55%32. вы можете получить этот бит).

person banarun    schedule 18.03.2013
comment
Да, но тогда индексация затруднена. - person Keith Thompson; 18.03.2013
comment
Вы предполагаете, что целое число ровно 32 бита. Это верно даже не для всех реализаций C. - person Keith Thompson; 18.03.2013
comment
@Keith, или вы можете использовать «char» для более простой реализации - person banarun; 18.03.2013
comment
Хорошо, сколько бит в char? А char подписано или не подписано? Оба ответа различаются даже для соответствующих реализаций C. Попытка сделать его языково-независимым еще сложнее. - person Keith Thompson; 18.03.2013
comment
не имеет значения, когда вы используете побитовое. Char всегда использует 8 бит. - person banarun; 18.03.2013
comment
Неправильно. В C char составляет минимум 8 бит; он может быть больше (компиляторы для некоторых DSP делают char 16 или 32 бита). CHAR_BIT говорит вам, сколько битов в char (или, что то же самое, в байте). И обычный char может быть как подписанным, так и беззнаковым; вы хотите использовать unsigned char для побитовых операций. В Java char по определению составляет 16 бит. В Java, если я правильно помню, char определяется как ровно 16 бит. - person Keith Thompson; 18.03.2013

В C++ это можно сделать очень просто, используя один из двух контейнеров стандартной библиотеки:

std::vector<bool>

Эта специализация стандартного вектора действует (почти) как любой другой вектор, но сжимает его содержимое до одного бита на элемент. Помимо удовольствия от этого факта, вы можете просто обращаться с ним как с вектором:

// Create a vector of 10000 booleans
std::vector<bool> lots_of_bits(10000);
// Set all the odd ones to true
for (int i = 1; i < lots_of_bits.size(); i += 2) {
  lots_of_bits[i] = true;
}
// Add another 100 trues at the end
for (int j = 0; j < 100; ++j) {
  lots_of_bits.push_back(true);
}
// etc.

std::bitset<N>

«Новый, улучшенный» битовый вектор, который не претендует на роль стандартного контейнера. В частности, он имеет фиксированный размер, и вам нужно знать размер во время компиляции. Это может быть немного ограничительным, но в остальном это довольно полезный класс. Как и std::vector<bool>, он реализует оператор [] для получения и установки отдельных битов. Он также поддерживает побитовые логические операторы &, |, '^' и ~ (и, или, xor и нет), а также битовые сдвиги влево и вправо и некоторые другие утилиты.

person rici    schedule 18.03.2013

Вас беспокоит, что для доступа к битовому номеру n требуется сдвиг n раз? Если это так, вы можете решить проблему, разделив свои 10 000 битов на 10 000 / 8 сегментов, используя массив символов (предполагая, что здесь C или C++). Теперь вы можете получить доступ к биту номер n, выяснив, в какой корзине находится этот бит (n / 8), а затем в какой позиции внутри корзины (n % 8). Затем вы просто делаете маскировку. Не требуется дополнительное хранилище (кроме заполнения в конце, поэтому несколько дополнительных битов, если у вас нет идеального кратного 32 бита).

person jacobm    schedule 18.03.2013
comment
Используйте CHAR_BIT вместо 8, если вам нужна полная переносимость, и используйте unsigned char вместо простого char, который может быть как подписанным, так и беззнаковым. - person Keith Thompson; 18.03.2013