Создание списка с двоичными числами в двоичном представлении в Python - PullRequest
3 голосов
/ 05 сентября 2011

У меня есть очень большой список 0 и 1, которые представлены как целые числа - по умолчанию - python, я думаю: [randint(0, 1) for i in range(50*98)]

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

Можно ли построить список действительных двоичных чисел в python?

С уважением, Bruno

РЕДАКТИРОВАТЬ : Спасибо всем.
Из ответов, которые я обнаружил, Python не делает этого по умолчанию, поэтому я нашел эту библиотеку (которая установлена ​​Macports на OSX, так что это избавляет меня от некоторых проблем), которая выполняет битовые операции: питон-битовая

Ответы [ 5 ]

4 голосов
/ 05 сентября 2011

Используется модуль bitstring и создается объект BitArray из вашего списка:

from bitstring import BitArray
b = BitArray([randint(0, 1) for i in range(50*98)])

Внутренне это теперь хранится упакованным как байты, поэтому займет значительно меньше памяти. Вы можете нарезать, индексировать, проверять и устанавливать биты и т. Д. С помощью обычной записи и дополнительных методов, таких как set, all и any чтобы изменить биты.

Чтобы вернуть данные в виде двоичной строки, просто используйте b.bin, а для вывода упакованных в байты данных используйте b.tobytes(), который будет заполняться нулевыми битами до границы байта.

2 голосов
/ 05 сентября 2011

Как уже сказал Делнан в комментарии, вы не сможете использовать действительные двоичные числа , если вы имеете в виду побитовое эквивалентное использование памяти.

Целые числа (или длинные)конечно, действительные двоичные числа в том смысле, что вы можете обращаться к отдельным битам (используя побитовые операторы, но это легко спрятать в классе).Кроме того, long объекты могут стать произвольно большими, т.е. вы можете использовать их для симуляции произвольно больших наборов битов.Это не будет очень быстро, если вы сделаете это на Python, но не очень сложно и хорошее начало.

Используя вышеописанную схему двоичной генерации, вы можете сделать следующее:

reduce(
    lambda (a, p), b: (b << p | a, p + 1), 
    (random.randint(0, 1) for i in range(50*98)),
    (0, 0)
)[0]

Конечно, random поддерживает произвольно большие верхние границы, поэтому вы можете сделать именно это:

r = random.randint(0, 2**(50*98))

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

1 голос
/ 05 сентября 2011

Это называется битовый вектор или битовый массив.Попробуйте, например, BitVector .Если вы хотите реализовать это самостоятельно, вам нужно использовать числовой объект, а не список, и использовать побитовые операции для переключения битов, например

 bitmap = 0
 bit = (1 << 24)
 bitmap |= bit  # enable bit
 bitmap &= ~bit # disable bit
0 голосов
/ 05 сентября 2011

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

0 голосов
/ 05 сентября 2011

Кажется, вам нужен какой-то набор битов.Я не уверен, что этот пример полностью соответствует вашим потребностям, но стоит попробовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...