【问题标题】:Flip bitmask horizontally [duplicate]水平翻转位掩码[重复]
【发布时间】:2016-11-17 10:41:23
【问题描述】:

有没有简单的方法来水平翻转位掩码,单线? 它应该执行以下操作:

0b1010101111001101 -> 0b1011001111010101 

一个直接的解决方案是一点一点地做:

uint16 flipUint16Horizontally(uint16 bitmask)
{
    uint16 flippedMask = 0;
    for(unsigned int bit = 0; bit < 16; ++bit)
    {
        uint16 currentBit = (bitmask & (1 << bit)) >> bit;
        flippedMask |= currentBit << (15 - bit);
    }
    return flippedMask;
}

有没有更优雅的方式?

【问题讨论】:

  • 定义优雅。
  • @2501: 不是愚蠢的方式 ;-)
  • 你可以找到几种方法here;但是,没有一个想法可以称为“单线”。
  • “单线”和“不笨的方式”通常不兼容。
  • @Lundin 你能不能关闭它,我已经错误地使用了我的投票并且不得不恢复?谢谢。 stackoverflow.com/questions/2253166/reverse-bit-pattern-in-c

标签: c bit-manipulation


【解决方案1】:

假设你有一个uint16,一个查找表。这是反向的一个衬里,当然初始化需要更多的工作。它也不一定是最快的方式,因为这是一个相当大的表,你可能会相对随机地索引它,这很容易导致缓存未命中。仍然很简单,而且占用空间要少得多:一个反转字节的查找表。以显而易见的方式使用它:

return (bitreverse[x & 0xFF] << 8) | bitreverse[x >> 8];

当然,你仍然需要处理初始化,但速度不那么重要。

有一种(在我看来)更优雅但更复杂的方法,只使用一些按位运算(并且没有完全难以理解的余数运算或类似的东西),反转第一个相邻位,然后是相邻的 2 位片段,然后相邻的半字节,依此类推,每一步将反转事物的宽度加倍,直到最后所有位都“全局”反转。顺便把这些步骤重新排序,有一种方法可以用更少的操作,但也更少的 ILP 来编写它们。

x = ((x & 0x5555) << 1) | ((x >> 1) & 0x5555); // swap bits
x = ((x & 0x3333) << 2) | ((x >> 2) & 0x3333); // swap 2-bit pieces
x = ((x & 0x0f0f) << 4) | ((x >> 4) & 0x0f0f); // swap nibbles
return (x >> 8) | (x << 8); // optimized last step

【讨论】:

    猜你喜欢
    • 2019-11-26
    • 2011-12-08
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-21
    相关资源
    最近更新 更多