我们说我有一个整数,因此它的二进制表示是:
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次。
但我不确定是否有更好的方法,或者我是否遗漏了更为简单的事情。
答案 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;
}
}