Перестановка пары бит в байте

У меня есть произвольное 8-битное двоичное число, например, 11101101

Мне нужно поменять все пары битов, например:

Перед заменой: 11-10-11-01 После замены: 11-01-11-10

Меня попросили в интервью!

Ответ 1

В псевдокоде:

x = ((x & 0b10101010) >> 1) | ((x & 0b01010101) << 1)

Он работает, обрабатывая младшие бит и высокие бит каждой битовой пары отдельно, а затем комбинируя результат:

  • Выражение x & 0b10101010 извлекает высокий бит из каждой пары, а затем >> 1 сдвигает его в положение с низким битом.
  • Аналогично, выражение (x & 0b01010101) << 1 извлекает младший бит из каждой пары и сдвигает его в положение с высоким битом.
  • Затем две части объединяются с использованием побитового OR.

Поскольку не все языки позволяют писать бинарные литералы напрямую, вы можете записать их, например, в шестнадцатеричном формате:

Binary        Hexadecimal  Decimal 
0b10101010    0xaa         170
0b01010101    0x55         85

Ответ 2

  • Создайте две битные маски, содержащие все четные биты и один, содержащий неравные биты (10101010 и 01010101).
  • Использовать побитовое - и фильтровать вход в два числа, один из которых имеет все четные разряды, а другой - все неравномерные биты, обнуленные.
  • Сдвиньте число, содержащее только четные бит, один бит влево, а другой - один бит вправо.
  • Использовать побитовое соединение или объединить их вместе.

Пример для 16 бит (не действительный код):

short swap_bit_pair(short i) {
    return ((i & 0101010110101010b) >> 1) | ((i & 0x0101010101010101b) << 1));
}

Ответ 3

b = (a & 170 >> 1) | (a & 85 << 1)

Ответ 4

Самое элегантное и гибкое решение, как утверждают другие, - применять маску "гребенка" как к четному, так и к нечетному битам отдельно, а затем, смещая их влево и вправо соответственно в одном месте, чтобы объединить их с помощью побитового или.

Еще одно решение, о котором вы можете подумать, использует относительно небольшой размер вашего типа данных. Вы можете создать таблицу поиска из 256 значений, которая статически инициализируется значениями, которые вы хотите выводить на ваш вход:

const unsigned char lookup[] = { 0x02, 0x01, 0x03, 0x08, 0x0A, 0x09, 0x0B ...

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

unsigned char out = lookup[ 0xAA ];

out будет содержать 0x55

Это более громоздко и менее гибко, чем первый подход (что, если вы хотите перейти от 8 бит к 16?), но имеет подход, который будет значительно быстрее, если выполнить большое количество этих операций.

Ответ 5

Предположим, что ваш номер num.

Сначала найдите бит четной позиции:
num & oxAAAAAAAA

Второй шаг найти бит нечетной позиции:
num & ox55555555

Третий шаг изменения позиции нечетного положения для четного позиционирования бит и четного бита позиции в бит нечетного положения:
Even = (num & oxAAAAAAAA)>>1
Odd = (num & 0x55555555)<<1

Последний шаг... result = Even | Odd

Результат печати

Ответ 6

Сначала я бы назвал его "длинным", то есть несколькими очевидными, явными этапами, и использовал это, чтобы проверить, что модульные тесты, которые у меня были на месте, функционировали правильно, а затем переходят только к более эзотерическим решениям для обработки бит если бы у меня была потребность в производительности (и эта дополнительная производительность была достигнута указанными улучшениями)

Код для людей сначала, второй - компьютеры.