【问题标题】:Fastest way to count number of bit transitions in an unsigned int计算无符号整数中位转换数的最快方法
【发布时间】:2009-01-23 09:17:15
【问题描述】:

我正在寻找计算unsigned int 中位转换次数的最快方法。

如果 int 包含:0b00000000000000000000000000001010

转换次数为:4

如果 int 包含:0b00000000000000000000000000001001

转换次数为:3

语言是 C。

【问题讨论】:

    标签: c bit counting


    【解决方案1】:
    int numTransitions(int a)
    {
      int b = a >> 1; // sign-extending shift properly counts bits at the ends
      int c = a ^ b;  // xor marks bits that are not the same as their neighbors on the left
      return CountBits(c); // count number of set bits in c
    }
    

    有关CountBits 的有效实施,请参阅http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel

    【讨论】:

    • 使用 shift + xor 也是我的第一个想法。
    【解决方案2】:

    最快取决于您的情况: 当您将数据类型指定为常量大小(无符号整数)时,可以使用查找表。但是,当您仅在初始化表的恒定开销太大时才需要此操作时,尽管通过 int 进行扫描+计数要快得多。

    我猜总体上最好的组合是:查找表中的字节或字(256 或 64k 条目不是那么多),然后按字节/字的最后一位/第一位组合。

    【讨论】:

    • 256 字节的查找表相当合理,但 64k 的查找表肯定会破坏 L1 缓存。
    【解决方案3】:

    在 C/C++ 中,我会执行以下操作:

    unsigned int Transitions(unsigned int value)
    {
        unsigned int result = 0;
    
        for (unsigned int markers = value ^ (value >> 1); markers; markers = markers >> 1)
        {
            if (markers & 0x01) result++;
        }
    
        return result;
    }
    

    【讨论】:

    • 我认为你的实现中有一个错误:如果我给它:0x8000000b = 0b10000000000000000000000000001011 其中有 4 个状态,你的函数计数为 5!
    • 这仅仅是因为迭代不限于 32 位(以减少操作数量),我想您可以添加一个额外的检查,但这会添加一些操作会减慢它的速度.此实现基本上是 Crashworks 解决方案的紧凑版本。
    【解决方案4】:

    这是使用算术移位 + xor 和 Kernighan 的位计数方法的代码:

    int count_transitions(int x)
    {
        assert((-1 >> 1) < 0); // check for arithmetic shift
        int count = 0;
        for(x ^= (x >> 1); x; x &= x - 1)
            ++count;
        return count;
    }
    

    【讨论】:

      【解决方案5】:

      什么语言?

      我会循环 64 次,然后对您的数字进行位移以检查这些位,然后存储前一个位并将其与当前位进行比较。如果不同,请增加您的计数。

      【讨论】:

        【解决方案6】:

        好的,您的意思是,如果您遍历 0-s 和 1-s 的字符串,则计算每次出现 0 跟随 1 或 1 跟随 0 的次数。

        这很容易通过移出位并计算变化:

        transitions(n)
          result = 0
          prev = n mod 2
          n = n div 2
          while n<>0 
            if n mod 2 <> prev then
              result++
              prev = n mod 2
            fi
            n = n div 2
          elihw
          return result
        

        你可以用 shift 替换 mod 和 div。

        【讨论】:

          猜你喜欢
          • 2012-03-23
          • 1970-01-01
          • 2019-02-27
          • 1970-01-01
          • 2013-09-01
          • 2017-09-05
          • 2016-08-17
          • 1970-01-01
          • 2018-11-05
          相关资源
          最近更新 更多