C# C语言中的Java Integer.highestOneBit#
我一直在努力寻找一个完全替代C#中Java的C# C语言中的Java Integer.highestOneBit#,c#,bit-manipulation,C#,Bit Manipulation,我一直在努力寻找一个完全替代C#中Java的Integer.highestOneBit(int) 我甚至试着找到它的源代码,但都没有用 JavaDocs告诉我们这个函数: 返回一个int值,该值最多包含一个一位,位于指定int值中最高阶(“最左边”)一位的位置 那么我该如何在C#中实现这一点呢?非常感谢您提供的任何帮助或链接/重定向。提供了一个可以在C#中工作的实现,只需进行一些修改: public static uint highestOneBit(uint i) { i |= (i
Integer.highestOneBit(int)
我甚至试着找到它的源代码,但都没有用
JavaDocs告诉我们这个函数:
返回一个int值,该值最多包含一个一位,位于指定int值中最高阶(“最左边”)一位的位置
那么我该如何在C#中实现这一点呢?非常感谢您提供的任何帮助或链接/重定向。提供了一个可以在C#中工作的实现,只需进行一些修改:
public static uint highestOneBit(uint i)
{
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
return i - (i >> 1);
}
它基本上用1s填充低于最高位的所有位,然后删除除最高位以外的所有位
示例(仅使用16位而不是32位):
您可以为
int
类型编写自己的扩展方法:
public static class Extensions
{
public static int HighestOneBit(this int number)
{
return (int)Math.Pow(2, Convert.ToString(number, 2).Length - 1);
}
}
因此,它可以用作
int number = 170;
int result = number.HighestOneBit(); //128
或者直接
int result = 170.HighestOneBit(); //128
下面是它的工作原理:
ToString(number,2)
以二进制形式写入我们的数字(例如:10101010代表170)。然后,我们使用第一位位置(长度-1)来计算2^(第一位位置)
的值,在本例中为128。最后,由于Math.Pow
返回一个double
,我们将其向下转换为int更新:.NET Core 3.0引入,它直接映射到底层CPU的位前导零计数指令,因此非常高效
public static uint highestOneBit(uint i)
{
返回i==0?0:1;
v |=v>>2;
v |=v>>4;
v |=v>>8;
v |=v>>16;
v++;//现在v是2的下一个幂
v>>=1;//获取2的上一次幂
}
:
public static uint highestOneBit(uint v)
{
常量int multipledBruijnbitPosition[32]=
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |=v>>1;
v |=v>>2;
v |=v>>4;
v |=v>>8;
v |=v>>16;
返回1>27];
}
这是一种对位执行操作的非常昂贵的方法。@JLRishe是的,它是。但至少您不必从uint
来回转换。除非连续执行超过1000万次,否则差异并不明显。但我认为位移位也很昂贵:(@AmatuerDev在500万次迭代的基准测试中,这些位移位的成本大约要低17倍。在大约100k次迭代时,它会变得很明显,执行起来可能需要几毫秒。@Pierre Luccineault如果使用位,通常应该使用无符号值。我的答案可以用int
而不是uint
很好,但是它会为使用第16位的值生成不正确的结果(并且您当前确实会为这些值生成不正确的结果)。刚刚根据@Pierre Luc的答案测试了此方法的输出。它保持不变。因此我猜这也是一个有效的实现。从长远来看,这将是理想的方法。我添加了此函数作为处理UINT上highestOneBit操作的重载。为什么只I |=(I>>8);
对于大于16位且具有零字节的值(如0x02300000@LưuVĩnhPhúc我的错误。我错误地认为int是16位的。你总能在GrepCode.com上找到任何标准Java库的源代码。示例:
int result = 170.HighestOneBit(); //128