【问题标题】:Get bit offset in C++在 C++ 中获取位偏移
【发布时间】:2012-01-04 15:11:58
【问题描述】:

我有一个 int 参数,可能的值为 1,2,4,8,16,32,64。

我需要知道当前值的位偏移量,即每个值分别返回 1、2、3、4、5 或 6。

实现这一目标的最简单方法是什么?

【问题讨论】:

  • 你的意思是 2 的幂(6 不是 1)吗?在这种情况下,“位偏移”将以 2 为底数?
  • 是的,请澄清。最好的问候,
  • 天真的方法是循环和测试,但可能有一条本机 CPU 指令在一条指令中执行此操作。 (“获取最低(或最高)有效位”)
  • 抱歉,6 不应该在那里,我知道使用以下方法解决这个问题:log((double)val) / log(2.0);但我认为这不是正确的方法
  • MSVC: _BitScanForward GCC: __builtin_ctz (最简单,因为你实际上不需要编写任何代码,只需调用一个已经存在的函数)

标签: c++ bit-manipulation offset


【解决方案1】:

这里有多个答案:http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious 最简单的是,假设您的输入值在 unsigned int v 中:

unsigned int r = 0; // r will be lg(v)

while (v >>= 1) // unroll for more speed...
{
  r++;
}

但它会在这个过程中改变 v。

编辑:在你的情况下,如果你 100% 确定你的输入是 int 和 2 的幂,那么查找表可能是最简单和最快的

【讨论】:

  • 字节序与它有什么关系?
  • 我很确定您的代码是正确的,而不考虑运行它的硬件系统的字节顺序。
  • 好的,根据stackoverflow.com/questions/1041554/…字节序不是问题,我编辑了我的回复
  • 幸运的是它与字节序无关,否则我们将成为皇家 scr*wed。
【解决方案2】:

这是一个版本,对于 32 位值最多只进行 5 次迭代,这与 lezebulon 的答案不同,最坏的情况是 32 次迭代。适应 64 位值会使这个版本的迭代次数增加到 6 次,而另一个最坏的情况下增加到 64 次。

int get_pos (unsigned v)
{
  int s=16,p=0,m=0xffff;

  while (s)
  {
    if (v>>s) p += s;
    v = (v | (v >> s)) & m;
    s >>= 1;
    m >>= s;
  }

  return p;
}

【讨论】:

    【解决方案3】:

    您需要做的就是每次循环并移动一点。但是有一种使用开关盒的更快方法。为您列出两者。

    //more code but awesomely fast
    int getBitOffset1(int d) {
      switch(d) {
        case 1: return 1;
        case 2: return 2;
        case 4: return 3;
        case 8: return 4;
        case 16: return 5;
        case 32: return 6;
        /* keep adding case upto sizeof int*8 */
      }
    }
    
    //less code, the loop goes 64 times max
    int getBitOffset2(int d) {
      int seed=0x01;
      int retval=0;
      do{
        if(seed<<retval == d) {
          break;
        }
        retval++;
      }while(retval<=sizeof(int)*8);
      return retval+1;
    }
    
    int main() {
        printf("%d\n", getBitOffset2(32));
        printf("%d\n", getBitOffset2(1));
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      相关资源
      最近更新 更多