负到-1,0到0,正到1

时间:2010-07-06 14:08:46

标签: .net

我有一个枚举MyEnum (Neg -1; None 0; Pos 1)

我使用CompareTo()的结果来初始化该枚举的对象。

.NET中执行此操作的性能最高的方式是什么(负数为-1,0到0,正数为1)?

NB。
CompareTo()返回一个Integer值..

9 个答案:

答案 0 :(得分:13)

查看Math.Sign

答案 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)

测试结果(双核,x86):

''''''''''''''''''''' 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;
        }
    }  }  

(例如编辑)