我有一个枚举MyEnum (Neg -1; None 0; Pos 1)
。
我使用CompareTo()
的结果来初始化该枚举的对象。
.NET中执行此操作的性能最高的方式是什么(负数为-1,0到0,正数为1)?
NB。
CompareTo()
返回一个Integer值..
答案 0 :(得分:13)
答案 1 :(得分:11)
在.net框架中有一个名为Math.Sign
的内置方法
答案 2 :(得分:10)
正如@Henrik和@ knittl所说,你应该使用Math.Sign
。但是,如果您对.Net框架在幕后所做的事情感兴趣,则以下代码来自Reflector。
public static int Sign(int value)
{
if (value < 0)
{
return -1;
}
if (value > 0)
{
return 1;
}
return 0;
}
答案 3 :(得分:4)
Math.Sign(value)
答案 4 :(得分:3)
CompareTo的结果为负,零或正。如果查看其他答案,Math.Sign使用2个if语句返回int。
只需重新编码Math.Sign即可返回枚举。
(如果这不是作业,我会在那里给出一个代码示例,但你应该从中学习。)
之后,测试一下,看看性能最高的是什么。
答案 5 :(得分:3)
''''''''''''''''''''' DEBUG MODE '''
= 1 =
Division took 00:00:06.2482408 ms
BuiltInSign took 00:00:05.0293383 ms <<<
BitTestSign took 00:00:05.2092181 ms
CustomSign took 00:00:05.2512802 ms
= 2 =
Division took 00:00:06.2477787 ms
BuiltInSign took 00:00:05.0330921 ms <<<
BitTestSign took 00:00:05.2114098 ms
CustomSign took 00:00:05.2556966 ms
= 3 =
Division took 00:00:06.2506690 ms
BuiltInSign took 00:00:05.0388615 ms <<<
BitTestSign took 00:00:05.2306954 ms
CustomSign took 00:00:05.2512391 ms
''''''''''''''''''' RELEASE MODE '''
= 1 =
Division took 00:00:01.0974078 ms
BuiltInSign took 00:00:00.3195232 ms
BitTestSign took 00:00:00.6392142 ms
CustomSign took 00:00:00.3194230 ms <<<
= 2 =
Division took 00:00:01.1007138 ms
BuiltInSign took 00:00:00.3197784 ms <<<
BitTestSign took 00:00:00.6395294 ms
CustomSign took 00:00:00.3202774 ms
= 3 =
Division took 00:00:01.0977087 ms
BuiltInSign took 00:00:00.3194622 ms <<<
BitTestSign took 00:00:00.6394220 ms
CustomSign took 00:00:00.3201607 ms
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Stopwatch sw = new Stopwatch();
MyEnum myEnum = MyEnum.None;
const int max = 100000000;
sw.Start();
for (int i = -max; i < max; i++)
{
myEnum = Division(i);
}
sw.Stop();
Console.WriteLine("Division took {0} ms", sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = -max; i < max; i++)
{
myEnum = BuiltInSign(i);
}
sw.Stop();
Console.WriteLine("BuiltInSign took {0} ms", sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = -max; i < max; i++)
{
myEnum = BitTestSign(i);
}
sw.Stop();
Console.WriteLine("BitTestSign took {0} ms", sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = -max; i < max; i++)
{
myEnum = CustomSign(i);
}
sw.Stop();
Console.WriteLine("CustomSign took {0} ms", sw.Elapsed);
}
private MyEnum Division(int value)
{
return value == 0 ? 0 : (MyEnum)(value / Math.Abs(value));
}
private MyEnum BuiltInSign(int value)
{
return (MyEnum)Math.Sign(value);
}
private MyEnum CustomSign(int value)
{
if (value < 0)
return MyEnum.Neg;
if (value > 0)
return MyEnum.Pos;
return MyEnum.None;
}
MyEnum BitTestSign(int value)
{
// Shifts the variable over 31 places,
// if the MSB is 1, the statement is true
if ((value >> 31) == 1)
{
return MyEnum.Neg;
}
else
{
if (value == 0)
{
return MyEnum.None;
}
else
{
return MyEnum.Pos;
}
}
}
private enum MyEnum
{
Pos = 1,
None = 0,
Neg = -1
}
}
答案 6 :(得分:1)
.NET内部存储整数作为两个补码。因此,如果您想尝试其他方法,请检查并确定是否设置了最重要的位。这可能会或可能不会更快,但它应该很容易适合您的测试框架。
伪代码:
if(num == 0)
return 0;
if(num has msb set)
return -1;
return 1;
答案 7 :(得分:0)
如果我理解正确,你想要为负值返回-1,为零值返回0,为正值返回1.
我会选择:
public static MyEnum GetSign(int value)
{
return value == 0 ? 0 : (MyEnum)(value / Math.Abs(value));
}
或者我弄错了什么?
答案 8 :(得分:0)
您可以检查变量的最高位(在二进制补码中,如果最高位为1,则为负数)。如果您的最高有效位为0,请检查该值是否为0.相应地返回一个值。
int Sign(int value){
if (value >> 31) { //Shifts the variable over 31 places, if the MSB is 1, the statement is true
return -1;
} else {
if (value == 0){
return 0;
} else {
return 1;
}
} }
(例如编辑)