3 Stimmen

Negativ bis -1, 0 bis 0, positiv bis 1

Ich habe eine Aufzählung MyEnum (Neg -1; None 0; Pos 1) .

Ich verwende das Ergebnis von CompareTo() um ein Objekt dieser Aufzählung zu initialisieren.

Was ist die am leistungsfähigsten wie man das in .NET machen kann (Negativ zu -1, 0 zu 0, positiv zu 1)?

NB.
CompareTo() gibt einen Integer-Wert zurück..

2 Stimmen

@knittl : denken Sie, dass die Abteilung am leistungsfähigsten ist?

9 Stimmen

@knittl macht .NET-Map 0/0 a 0 ?

0 Stimmen

Wenn dem Enum bereits die Werte -1/0/1 zugewiesen sind, wird CompareTo() immer -1, 0 oder 1 zurückgeben (niemals einen anderen Wert). Wenn ich also richtig verstehe, können Sie einfach Folgendes tun, um einen Wert vom Typ MyEnum zu erhalten: MyEnum myval = (MyEnum)x.CompareTo(y);

3voto

serhio Punkte 27312

Testergebnisse (Dual Core, 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

Code:

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

1voto

Donnie Punkte 43338

NET speichert intern Ints als Zweierkomplement. Wenn Sie also etwas anderes ausprobieren wollen, prüfen Sie, ob das höchstwertige Bit gesetzt ist. Dies kann schneller sein oder auch nicht, aber es sollte leicht in Ihr Test-Framework passen.

Pseudocode:

if(num == 0)
  return 0;

if(num has msb set)
  return -1;

return 1;

0voto

Turing Complete Punkte 929

Wenn ich das richtig verstehe, wollen Sie -1 für negative Werte, 0 für Nullwerte und 1 für positive Werte zurückgeben.

Ich würde mitgehen:

public static MyEnum GetSign(int value)
{
    return value == 0 ? 0 : (MyEnum)(value / Math.Abs(value));
}

Oder habe ich etwas falsch verstanden?

0voto

Jan Gorzny Punkte 1692

Sie könnten das höchstwertige Bit der Variablen überprüfen (im Zweierkomplement, wenn das höchstwertige Bit 1 ist, haben Sie eine negative Zahl). Wenn Ihr höchstwertiges Bit 0 ist, prüfen Sie, ob der Wert 0 ist. Geben Sie einen entsprechenden Wert zurück.

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

(bearbeitet für ein Beispiel)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X