使用bit hack将字节转换为特定掩码

时间:2011-01-31 08:47:48

标签: language-agnostic bit-manipulation

我的数字是二进制表示0000abcd

如何以最少的操作数将其转换为0a0b0c0d? 如何将0a0b0c0d转换回0000abcd

我在这里寻找解决方案: http://graphics.stanford.edu/~seander/bithacks.html和其他

一般来说问题比描述的要多一些。

第一个号码a₁b₁c₁d₁a₂b₂c₂d₂和第二个号码a₃a₄b₃b₄c₃c₄d₃d₄

如果(a₁a₂ = 0)则清除a₃a₄,if {a₃和{{1} } = a₄)然后清除0a₁

我的解决方案:

a₂

更新:(感谢@AShelly)

    a₁b₁c₁d₁a₂b₂c₂d₂
OR  0 0 0 0 a₁b₁c₁d₁ ( a₁b₁c₁d₁a₂b₂c₂d₂ >> 4)
    ----------------
    0 0 0 0 a b c d
? (magic transformation)
    ? ? ? ? ? ? ? ?
    ----------------
    0 a 0 b 0 c 0 d
OR  a 0 b 0 c 0 d 0  (0 a 0 b 0 c 0 d << 1)
    ----------------
    a a b b c c d d
AND a₃a₄b₃b₄c₃c₄d₃d₄
    ----------------
    A₃A₄B₃B₄C₃C₄D₃D₄ (clear bits)

使用常量x = a₁b₁c₁d₁a₂b₂c₂d₂ x = (x | x >> 4) & 0x0F x = (x | x << 2) & 0x33 x = (x | x << 1) & 0x55 x = (x | x << 1) y = a₃a₄b₃b₄c₃c₄d₃d₄ y = (y | y >> 1) & 0x55 y = (y | y >> 1) & 0x33 y = (y | y >> 2) & 0x0F y = (y | y << 4) 0x0F0F0F0F0x33333333(以及64位的两倍长)来处理32位。

4 个答案:

答案 0 :(得分:2)

如果您正在寻找最少的操作,请使用查找表。

答案 1 :(得分:0)

你无法一次性完成,你应该逐位移位:

伪代码:

    X1 = a₁b₁c₁d₁
    X2 = a₂b₂c₂d₂
    Bm = 1 0 0 0 // Bit mask

    Result = 0;

    while (/* some bytes left */)
    {
       Result += (X1 and Bm) << 1 or (X2 and Bm);
       Bm = Bm shr 1
       Result = Result shl 2;
    }

结果你将获得a1a2b1b2c1c2d1d2

答案 2 :(得分:0)

我认为使用二进制算法和x86或x64处理器架构在较少的操作中不可能(没有查找表)。纠正我,如果我错了,但你的问题是移动位。拥有abcd位,您希望在一次操作中获得0a0b0c0d位。当你看到'a','b','c'和'd'必须经过多少位时,问题就出现了。

'a' was 4-th, became 7-th, distance travelled 3 bits
'b' was 3-rd, became 5-th, distance travelled 2 bits
'c' was 2-nd, became 3-rd, distance travelled 1 bit
'd' was 1-st, became 1-st, distance travelled 0 bits

没有这样的处理器指令会将这些位动态移动到不同的距离。虽然如果你有相同数字的不同输入表示是免费的,例如你已经预先计算了一个你在循环中使用的值,那么可能会获得一些优化,这就是你在使用其他知识时所获得的效果关于拓扑。您只需选择是否:

[4 cycles, n^0 memory]
[2 cycles, n^1 memory]
[1 cycle , n^2 memory]

答案 3 :(得分:0)

  

我有二进制数字   代表0000abcd。如何转换   它以0a0b0c0d为最小数量   操作

这不是“Interleave bits of X and Y",其中Y是0吗?Bit Twiddling Hacks Multiple Solutions不使用查找表。

  

如何将0a0b0c0d转换回0000abcd?

请参阅“How to de-interleave bits (UnMortonizing?)"