Python инвертирует двоичный шаблон в целое число

Sep 02 2020

Есть ли быстрая возможность перевернуть двоичное число в Python?

Пример: у меня есть число 11 в двоичном формате 0000000000001011 с 16 битами. Теперь я ищу быструю функцию f, которая возвращает 1101000000000000 (десятичное число 53248). Таблицы поиска не являются решениями, поскольку я хочу масштабировать их до 32-битных чисел. Спасибо за ваши усилия.

Редактировать:

Спектакли . Я тестировал код для всех шаблонов 2 ^ 16 несколько раз.

  • победителем являются частично справочные таблицы: 30 мс

  • 2-й int(format(num, '016b')[::-1], 2)из комментариев: 56 мс

  • 3-е место x = ((x & 0x00FF) << 8) | (x >> 8): 65 мс

  • Я не ожидал, что мой подход будет настолько ужасно медленным, но это так. ок. 320 мс. Небольшое улучшение за счет использования + вместо | 300 мс

  • bytes(str(num).encode('utf-8'))боролся за 2-е место, но почему-то код не давал правильных ответов. Скорее всего, потому что я ошибся, снова преобразовав их в целое число.

большое спасибо за ваш вклад. Я был очень удивлен.

Ответы

3 HL Sep 02 2020 at 04:36

Это может быть быстрее при использовании небольшой 8-битной таблицы поиска:

num = 11
# One time creation of 8bit lookup
rev = [int(format(b, '08b')[::-1], base=2) for b in range(256)]

# Run for each number to be flipped.
lower_rev = rev[num & 0xFF] << 8
upper_rev = rev[(num & 0xFF00) >> 8]
flipped = lower_rev + upper_rev
1 Ethan Sep 02 2020 at 03:55

Я думаю, вы можете просто использовать нарезку, чтобы получить то, что вы ищете:

b=bytes('0000000000001011'.encode('utf-8'))
>>> b
b'0000000000001011'
>>> b[::-1]
b'1101000000000000'
1 superbrain Sep 02 2020 at 04:27

Это есть, но в Python это кажется медленнее, чем предложенное Маттиасом решение int-> str-> int.

x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1)
x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2)
x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4)
x = ((x & 0x00FF) << 8) | (x >> 8)
1 DuDa Sep 02 2020 at 03:48

Мой текущий подход состоит в том, чтобы получить доступ к битам с помощью сдвига битов и маски и сдвинуть их в зеркальном номере, пока они не достигнут места назначения. Тем не менее я чувствую, что есть возможности для улучшения.

num = 11
print(format(num, '016b'))

right = num
left = 0
for i in range(16):
  tmp = right & 1
  left = (left << 1 ) | tmp
  right = right >> 1


print(format(left, '016b'))