高效的按位运算,找到最左边的位集索引

时间:2013-01-21 10:23:27

标签: c# bit-manipulation performance

C++中,我可以使用编译器特定的内在函数来查找左侧|最右侧的位集,如此thread中所示。

C#中有类似内容吗?或者我需要遍历所有位来实现它?

3 个答案:

答案 0 :(得分:3)

你走了。 Implementations adapted from here

// Implementation of Least|Most SigBitSet from http://aggregate.org/MAGIC/

using System;

namespace Demo
{
    internal class Program
    {
        private static void Main()
        {
            int value = 0x0ff0; // 0000111111110000

            Console.WriteLine(LeastSigBitSet(value).ToString("x")); // 0x0010
            Console.WriteLine(MostSigBitSet(value).ToString("x"));  // 0x0800
        }

        public static int LeastSigBitSet(int value)
        {
            return (value & -value);
        }

        public static int MostSigBitSet(int value)
        {
            value |= (value >> 1);
            value |= (value >> 2);
            value |= (value >> 4);
            value |= (value >> 8);
            value |= (value >> 16);

            return (value & ~(value >> 1));
        }
    }
}

unsigned int版本(可能是你想要的版本):

using System;

namespace Demo
{
    internal class Program
    {
        private static void Main()
        {
            uint value = 0x00ffff00; // 00000000111111111111111100000000

            Console.WriteLine(LeastSigBitSet(value).ToString("x")); // 0x0000100
            Console.WriteLine(MostSigBitSet(value).ToString("x"));  // 0x0800000
        }

        public static uint LeastSigBitSet(uint value)
        {
            return (value & 0u-value);
        }

        public static uint MostSigBitSet(uint value)
        {
            value |= (value >> 1);
            value |= (value >> 2);
            value |= (value >> 4);
            value |= (value >> 8);
            value |= (value >> 16);

            return (value & ~(value >> 1));
        }
    }
}

答案 1 :(得分:2)

对于像ffs这样的东西,无法访问特定于编译器的“内置”指令。您必须使用诸如位掩码和移位操作之类的常规代码实现。然而,这并不一定意味着你需要遍历所有的位:对于这些方法中的许多方法都有一些可怕的“常规”实现,做一些疯狂的“添加一些不明显的奇异常数”削减了大部分的分支和迭代,这在C#中完全没问题。如果您移植其中一个,请记住的主要事项是知道它是使用“签名”还是“无符号”右移;如果使用“签名”使用int(等);如果是“未签名”,请使用uint(等)。

答案 2 :(得分:0)

很多人在这里有复杂的解决方案......他说“有效”,所以如果他们能为你做这个伎俩,我会选择这些。

lsb=i&-i;
msb=(int)(((double)i >> 20) - 1023);