【问题标题】:How to de-interleave bits (UnMortonizing?)如何去交错位(UnMortonizing?)
【发布时间】:2011-03-09 09:54:24
【问题描述】:

从 32 位整数中解交织位的最有效方法是什么?对于这种特殊情况,我只关心奇数位,尽管我确信将任何解决方案推广到两组都很简单。

例如,我想将0b01000101 转换为0b1011。最快的方法是什么?

编辑:

在这个应用程序中,我可以保证偶数位全为零。我可以利用这一事实来提高速度或减少空间吗?

【问题讨论】:

    标签: bit-manipulation z-order-curve


    【解决方案1】:

    鉴于您知道在您的应用程序中每隔一个位都是 0,您可以这样做:

    x = (x | (x >> 1)) & 0x33333333;
    x = (x | (x >> 2)) & 0x0f0f0f0f;
    x = (x | (x >> 4)) & 0x00ff00ff;
    x = (x | (x >> 8)) & 0x0000ffff;
    

    第一步如下所示:

      0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p   x
    | 00a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0   x >> 1
      --------------------------------
    = 0aabbccddeeffgghhiijjkkllmmnnoop   x | (x >> 1)
    & 00110011001100110011001100110011   0x33333333
      --------------------------------
    = 00ab00cd00ef00gh00ij00kl00mn00op   (x | (x >> 1)) & 0x33333333
    

    然后第二步一次处理两个位,依此类推。

    【讨论】:

    • 这比我的 PC 上的 32 条目表测试得更快。
    • ...如果您不知道奇数位为零,请在前面输入x &= 0x55555555
    • 注意:提供的函数计算设置的偶数位,而在原始问题中它计算奇数位。您可以使用此函数通过先右移 1 来计算奇数位。
    【解决方案2】:

    就速度而言,16 位宽、2^32 个条目的查找表将很难被击败! 但是如果你没有那么多内存可以在一个 256 条目的表中进行四次查找, 加上一些班次和 AND 将它们缝合在一起,可能是一个更好的选择。或者,甜蜜点可能介于两者之间……这取决于您可用的资源,并且 初始化查找表的成本将如何分摊到您需要执行的查找次数中。

    【讨论】:

    • 我绝对没有那么多可用内存——我的目标是嵌入式平台。 256 条目表可能有效。我仍然对算法方法感兴趣。
    • @AShelly:一个起点是考虑每个潜在的一位必须“移动”(移位)到新位置的位置。例如,第 6 位右移 3 位,第 4 位右移 2 位,第 2 位右移 1 位,第 0 位不移动。然后,将这些移位量分解为二进制数。这是可行的,因为移位 3 位与移位 2 位然后再移位 1 位相同。使用位掩码选择需要移位的位。不过,这种方法可能比小型查找表更昂贵。
    • 在嵌入式平台上,尝试一个 16 项的表,一次处理 4 位。
    【解决方案3】:

    我不确定它会有多,但你可以做类似的事情

    int a = 0b01000101;
    int b = 0;
    int i = 0;
    while (a > 0) {
        b |= (a & 1) << i;
        a >>= 2;
    }
    

    这会将所有奇数部分从 a 中取出并放在 b 上。

    【讨论】:

    • 你在某个地方需要一个 i++。
    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 2020-10-23
    相关资源
    最近更新 更多