这是一个非常简单的问题,我认为这是家庭作业。 @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 更长且更容易出错。道德是相信你的编译器。