我正在实现一个库,其中广泛使用 .Net BitArray 类,并且需要与 Java BitSet.Cardinality() 方法等效的方法,即返回设置的位数的方法。我正在考虑将其实现为 BitArray 类的扩展方法。简单的实现是迭代和计算位集(如下所示),但我想要更快的实现,因为我将执行数千个集合操作并计算答案。有没有比下面的例子更快的方法?
count = 0;
for (int i = 0; i < mybitarray.Length; i++)
{
if (mybitarray [i])
count++;
}
这是我基于“最佳位计数方法”的解决方案http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
public static Int32 GetCardinality(BitArray bitArray)
{
Int32[] ints = new Int32[(bitArray.Count >> 5) + 1];
bitArray.CopyTo(ints, 0);
Int32 count = 0;
// fix for not truncated bits in last integer that may have been set to true with SetAll()
ints[ints.Length - 1] &= ~(-1 << (bitArray.Count % 32));
for (Int32 i = 0; i < ints.Length; i++)
{
Int32 c = ints[i];
// magic (http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel)
unchecked
{
c = c - ((c >> 1) & 0x55555555);
c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
c = ((c + (c >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
count += c;
}
return count;
}
根据我的测试,这比简单的 foreach 循环快大约 60 倍,并且仍然比 Kernighan 方法快 30 倍,在 1000 位的 BitArray 中大约 50% 位设置为 true。如果需要的话我还有一个 VB 版本。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)