代码之家  ›  专栏  ›  技术社区  ›  Ryan Peschel

考虑到限制,寻找更有效的弹出计数

  •  1
  • Ryan Peschel  · 技术社区  · 10 年前

    这个 popcount 函数返回输入中的1个数。 0010 1101 有一个 教皇计数 共4页。

    目前,我正在使用此算法获取 教皇计数 :

    private int PopCount(int x)
    {
        x = x - ((x >> 1) & 0x55555555);
        x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
        return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
    }
    

    这很好,我要求更多的唯一原因是因为这个操作运行得非常频繁,我正在寻找额外的性能增益。

    我正在寻找一种简化算法的方法,因为我的1总是正确对齐的。也就是说,输入将类似于 00000 11111 (返回5)或 00000 11111 11111 (返回10)。

    有没有一种方法可以基于这种约束来实现更高效的popcount?如果输入是 01011 11101 10011 ,它只会返回2,因为它只关心最正确的。似乎任何一种循环都比现有解决方案慢。

    1 回复  |  直到 10 年前
        1
  •  1
  •   Ben Voigt    10 年前

    这里是一个执行“查找最高集”(二进制对数)的C#实现。它可能比您当前的PopCount快,也可能不快,但肯定比使用真实的PopCount慢 clz 和/或 popcnt CPU指令:

    static int FindMSB( uint input )
    {
        if (input == 0) return 0;
        return (int)(BitConverter.DoubleToInt64Bits(input) >> 52) - 1022;
    }
    

    测试: http://rextester.com/AOXD85351

    以及没有条件分支的轻微变化:

    /* precondition: ones are right-justified, e.g. 00000111 or 00111111 */
    static int FindMSB( uint input )
    {
        return (int)(input & (int)(BitConverter.DoubleToInt64Bits(input) >> 52) - 1022);
    }