Это довольно простая проблема, которую я считаю домашней работой. @Tom сделал это немного сложнее, чем нужно.
Вы просто хотите извлечь каждый 4-й бит, начиная с наименее значимого, игнорируя 3 промежуточных нуля. Я дам вам алгоритм. Написание кода не должно быть трудным:
let x be the hex coded binary number to convert
let val be the binary result value, initially zero
let n be the bit position we're currently finding, initially zero
while x is not zero
let b be the least significant bit of x
update val to be val or (b shifted left by n bits)
increment n
update x to be x shifted right by 4 bits
Вот другой подход:
let val be 0
let hex_mask be 1
let bin_mask be 1
while hex_mask is not zero
if (x and hex_mask) is non-zero, then update val to be val or bin_mask
shift hex_mask left 4 bits
shift bin_mask left 1 bit
Добавление
Поскольку вы говорите, что это не домашняя работа, позвольте мне показать вам, что второе решение на самом деле - это решение только с побитовыми операторами, если у вас хороший компилятор.
Вот код:
uint16_t hex_coded_binary_value(uint16_t x) {
uint16_t val = 0;
for (uint16_t h = 1, b = 1; h; h <<=4, b <<= 1)
if (x & h) val |= b;
return val;
}
Если вы скомпилируете это с последней версией Apple clang
, вы получите:
mov eax, edi
and eax, 1
mov ecx, edi
shr ecx, 3
and ecx, 2
or ecx, eax
mov eax, edi
shr eax, 6
and eax, 4
or eax, ecx
shr edi, 9
and edi, 8
lea eax, [rdi + rax]
ret
Обратите внимание, никаких петель! Это все сдвиг, и, или, добавление и перемещение. gcc
использует инструкции условного перемещения, но также не имеет циклов.
Какой алгоритм обнаружил компилятор? Если бы вы кодировали на C, это выглядело бы примерно так:
val = (x & 1)
| ((x >> (4 - 1)) & (1 << 1))
| ((x >> (8 - 2)) & (1 << 2))
| ((x >> (12 - 3)) & (1 << 3));
Это складывается до
val = (x & 1) | ((x >> 3) & 2) | ((x >> 6) & 4) | ((x >> 9) & 8);
Обратите внимание, что результат имеет меньше операций, чем решение @ tom.
Это также компилируется по существу так же, как оригинал, но C длиннее и более подвержен ошибкам. Мораль в том, чтобы доверять вашему компилятору.