Представление Base-2 (двоичное) с использованием Python

Основываясь на Как вы выражаете двоичные литералы в Python, я думал о разумных, интуитивно понятных способах сделать этот каштан отображения целых чисел в форме с основанием 2. Это лучшее, что я придумал, но я хотел бы заменить его более совершенным алгоритмом или, по крайней мере, таким, который должен иметь невероятно быструю производительность.

def num_bin(N, places=8):
    def bit_at_p(N, p):
        ''' find the bit at place p for number n '''
        two_p = 1 << p   # 2 ^ p, using bitshift, will have exactly one
                         # bit set, at place p
        x = N & two_p    # binary composition, will be one where *both* numbers
                         # have a 1 at that bit.  this can only happen 
                         # at position p.  will yield  two_p if  N has a 1 at 
                         # bit p
        return int(x > 0)

    bits =  ( bit_at_p(N,x) for x in xrange(places))
    return "".join( (str(x) for x in bits) )

    # or, more consisely 
    # return "".join([str(int((N & 1 << x)>0)) for x in xrange(places)])
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
6
0
16 544
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

def _bin(x, width):
    return ''.join(str((x>>i)&1) for i in xrange(width-1,-1,-1))

_bin (x, 8) теперь даст заполненное нулями представление младших 8 битов x. Это можно использовать для построения таблицы поиска, позволяющей вашему конвертеру обрабатывать 8 бит за раз (или больше, если вы хотите выделить для него память).

_conv_table = [_bin(x,8) for x in range(256)]

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

def bin(x):
    if x == 0: 
        return '0' #Special case: Don't strip leading zero if no other digits
    elif x < 0:
        sign='-'
        x*=-1
    else:
        sign = ''
    l=[]
    while x:
        l.append(_conv_table[x & 0xff])
        x >>= 8
    return sign + ''.join(reversed(l)).lstrip("0")

[Edit] Изменен код для обработки целых чисел со знаком.
[Edit2] Вот некоторые временные характеристики различных решений. bin - это функция выше, constantin_bin - из Константин ответ, а num_bin - это исходная версия. Из любопытства я также попробовал 16-битный вариант таблицы поиска, описанный выше (bin16 ниже), и опробовал встроенную функцию bin () Python3. Все тайминги были для 100000 прогонов с использованием битовой комбинации 01010101.

Num Bits:              8       16       32       64      128      256
---------------------------------------------------------------------
bin                0.544    0.586    0.744    1.942    1.854    3.357 
bin16              0.542    0.494    0.592    0.773    1.150    1.886
constantin_bin     2.238    3.803    7.794   17.869   34.636   94.799
num_bin            3.712    5.693   12.086   32.566   67.523  128.565
Python3's bin      0.079    0.045    0.062    0.069    0.212    0.201 

Как видите, обработка длинных значений с использованием больших кусков действительно окупается, но ничто не сравнится с низкоуровневым кодом C встроенной функции python3 (который, как ни странно, кажется стабильно быстрее при 256 битах, чем 128!). Использование 16-битной таблицы поиска улучшает ситуацию, но, вероятно, этого не стоит, если она вам действительно не нужна, поскольку она использует большой кусок памяти и может вызвать небольшую, но заметную задержку запуска для предварительного вычисления таблицы.

Спасибо за более или менее полный ответ, который использует функцию bin () 2.6 или 3.0 :)

Gregg Lind 21.10.2008 20:29

Не крикливо-быстро, а прямолинейно:

>>> def bin(x):
...     sign = '-' if x < 0 else ''
...     x = abs(x)
...     bits = []
...     while x:
...             x, rmost = divmod(x, 2)
...             bits.append(rmost)
...     return sign + ''.join(str(b) for b in reversed(bits or [0]))

Он также быстрее, чем num_bin:

>>> import timeit
>>> t_bin = timeit.Timer('bin(0xf0)', 'from __main__ import bin')
>>> print t_bin.timeit(number=100000)
4.19453350997
>>> t_num_bin = timeit.Timer('num_bin(0xf0)', 'from __main__ import num_bin')
>>> print t_num_bin.timeit(number=100000)
4.70694716882

Более того, он действительно работает правильно (для моего определения "правильности" :)):

>>> bin(1)
'1'
>>> num_bin(1)
'10000000'

«Правильно» - это дело вкуса, в зависимости от порядка байтов Little и Big-Endian, а также от того, требуется ли заполнение или нет. Хотя рецепт неплохой.

Gregg Lind 10.10.2008 17:03

Другие вопросы по теме