获取每组位的连续索引的最快方法是什么?

时间:2015-03-22 02:36:00

标签: c# arrays binary bit-manipulation

我们说我有一个整数,因此它的二进制表示是:

1001 1011 0111 0001 0010 1100 1000 1111

我正在寻找获得每个设置位的连续索引的方法。我将数组元素从一个数组移动到另一个数组。元素的数量是1的数量。

在这个例子中,第一个数组的前4个元素将被移动到第二个数组的前4个指标(从右侧开始:LSB)。

然而,在那之后,第一个数组的第五个元素将转移到第二个数组的第8个索引,因为存在3个零的间隙(因此第8个索引=索引7)。

希望你现在可以看到这种模式。我想可能转换为字符串并进行循环,但这似乎相当慢。我也可以在循环中使用这样的一些位操作:

x & (x-1)清除下一个设置位

(int)Math.Log((x & ~(x - 1)), 2);找到下一个设置位。

还有一个解决方案,只需保持一个正在运行的索引并保持1和每次迭代换1次。

但我不确定是否有更好的方法,或者我是否遗漏了更为简单的事情。

1 个答案:

答案 0 :(得分:3)

我认为带有运行索引的简单循环应该可以正常工作。对Math.Log的调用肯定不会更快,De Bruijn也不会进行黑客操作。如果有可能在汇编/内在函数中找到c#中的前导/尾随0,那么可能会做得更好。

现在,我建议使用简单的循环,并在mask变为0时使用终止条件,如下所示:

static void CopyByMask<T>(UInt32 mask, T[] srcArray, T[] destArray)
{
    // Note: assumes arrays are appropriately sized.
    var srcPos = 0;
    for (var destPos = 0; mask != 0; destPos++)
    {
        if ((mask & 1) == 1)
            destArray[destPos] = srcArray[srcPos++];
        mask >>= 1;
    }
}