C# 如何获取位数组中的最后一个设置位?

C# 如何获取位数组中的最后一个设置位?,c#,.net,bit-manipulation,C#,.net,Bit Manipulation,获取位数组中最后一个设置位的有效(快速)方法是什么。(LINQ或simple backward for loop对于大型位图不是很快。我需要快速) 我看到下一个算法:通过BITARINS内部INT数组数据返回,使用一些编译器,如C++ + BITSCANTURE反向(不知道C中的模拟)。< / P> < P>如果您想要最后一个设置位的索引,您可以在C 6中这样做。 否则你就得这样做 var last = array.Select((b,i)=>{Index = i, Value = b})

获取位数组中最后一个设置位的有效(快速)方法是什么。(LINQ或simple backward for loop对于大型位图不是很快。我需要快速)
我看到下一个算法:通过BITARINS内部INT数组数据返回,使用一些编译器,如C++ + BITSCANTURE反向(不知道C中的模拟)。< / P> < P>如果您想要最后一个设置位的索引,您可以在C 6中这样做。 否则你就得这样做

var last = array.Select((b,i)=>{Index = i, Value = b})
                  .LastOrDefault(x => x.Value);
int? index = last == null ? (int?)null : last.Index;

无论哪种方式,如果所有位都为零,
索引
都将为
null

我认为除了从最后一位迭代到第一位,并询问是否设置了每个位之外,没有其他方法可以做。可以通过以下方式完成:

BitArray bits = ...;
int lastSet = Enumerable.Range(1, bits.Length)
                  .Select(i => bits.Length - i)
                  .Where(i => bits[i])
                  .DefaultIfEmpty(-1)
                  .First();
它应该返回最后一个位集,如果没有,则返回-1。我自己还没有测试过,所以可能需要一些调整

希望有帮助。

正常的解决方案:

    static long FindLastSetBit(BitArray array)
    {
        for (int i = array.Length - 1; i >= 0; i--)
        {
            if (array[i])
            {
                return i;
            }
        }

        return -1;
    }
反射解决方案(注意-依赖于
位数组的实现):


使用<代码> LINQ = >代码>数组实例.LAST()/<代码>在整型中更容易,因此如果您的数组足够短,您可能会考虑到。LINQ不快。我很伤心——“有效”。不,林克!可以做到这一点,只需实现bitscan,BitArray类只提供对单个位的访问,因此不能有效地跳过全部为零的整个字。您必须找到/编写位数组的另一个实现。Linq不快。我很伤心——“有效”。不,林克!您可以将LINQ的用法替换为从位数组末尾到前端的一个简单的
for
。我现在看到您编辑了这个问题,专门要求不使用LINQ,而不是从端到端进行迭代。我认为BitArray无法满足您的需求。我将使用一个自定义的位数组实现,它允许您访问内部int/long数组,这样您就可以一次询问32/64位是否都是0。Linq不是很快。我很伤心——“有效”。不,林克@“有效”是主观的。如果你想要更具体的答案,你应该更具描述性。在任何情况下,您都必须循环通过
位数组
,这正是Linq所做的。否则,如果要为此使用位运算符,则需要使用比
位数组
更基本的类型。
    static long FindLastSetBit(BitArray array)
    {
        for (int i = array.Length - 1; i >= 0; i--)
        {
            if (array[i])
            {
                return i;
            }
        }

        return -1;
    }
    static long FindLastSetBitReflection(BitArray array)
    {
        int[] intArray = (int[])array.GetType().GetField("m_array", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(array);

        for (var i = intArray.Length - 1; i >= 0; i--)
        {
            var b = intArray[i];
            if (b != 0)
            {
                var pos = (i << 5) + 31;
                for (int bit = 31; bit >= 0; bit--)
                {
                    if ((b & (1 << bit)) != 0)
                        return pos;

                    pos--;
                }

                return pos;
            }
        }

        return -1;
    }
    static unsafe long FindLastSetBitUnsafe(BitArray array)
    {
        int[] intArray = (int[])array.GetType().GetField("m_array", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(array);

        fixed (int* buffer = intArray)
        {
            for (var i = intArray.Length - 1; i >= 0; i--)
            {
                var b = buffer[i];
                if (b != 0)
                {
                    var pos = (i << 5) + 31;
                    for (int bit = 31; bit >= 0; bit--)
                    {
                        if ((b & (1 << bit)) != 0)
                            return pos;

                        pos--;
                    }

                    return pos;
                }
            }
        }

        return -1;
    }