虽然这段话有点长,但是它很快(在整个int范围内平均)
internal static readonly byte[] msbPos256 = new byte[] {
255, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
public static int SignificantBits(this int value) {
return HighBitPosition((uint)value) + 1;
}
public static int HighBitPosition(this ushort value) {
byte hiByte = (byte)(value >> 8);
if (hiByte != 0) return 8 + msbPos256[hiByte];
return (sbyte)msbPos256[(byte)value];
}
public static int HighBitPosition(this uint value) {
byte hiByte = (byte)(value >> 24);
if (hiByte != 0) return 24 + msbPos256[hiByte];
hiByte = (byte)(value >> 16);
return (hiByte != 0) ? 16 + msbPos256[hiByte] : HighBitPosition((ushort)value);
}
调用SignificantBits方法。需要注意的是,99.6%的int值可能会在32位中的前8个最高有效位(即32位中的前8位)之一具有最高有效位。这只需要进行右移操作、两个加法操作(其中一个可能会被编译器优化为递增操作)、一个!=0测试和一个数组引用。因此,对于大多数可能的值,速度非常快。要覆盖第二个8个最高有效位,需要进行额外的右移、!=0测试,这可以覆盖99.998%的可能int值。转换成其他类型不会带来太大开销。
您可以通过将msbPos256值增加1来省略+1操作。当我写这段代码时,我更感兴趣的是HighBitPosition函数而不是SignficantBits函数,这就是我为什么以我现在的方式添加了SignificantBits的原因。
如果我没记错,在测试各种技巧时,这比我最初用于此的DeBruijn技术更快。