2010-03-08 4 views
8

Ich habe ein Projekt, wo ich Arithmetik standardmäßig überprüft haben möchte, mit Ausnahme einer leistungsempfindlichen Stelle. Leider hat VB.Net keinen "ungeprüften" Block.Schnellste Möglichkeit, eine ungeprüfte ganzzahlige Addition in VB.Net zu machen?

Idealerweise hätte das Framework eine Art Integer-Typ mit explizit ungeprüfter Arithmetik, aber ich habe nichts dergleichen gefunden. Ich habe festgestellt, dass Ausdrucksbäume binäre Ausdrücke für ungeprüfte Operationen haben, aber der Delegat-Overhead hebt den unkontrollierten Vorteil (und dann einige) auf.

Momentan konvertiere ich die Eingaben in UInt64/Int64, bevor ich die Arithmetik ausführe, und dann zurück umwandelt (mit einem bitweisen And, um innerhalb des Bereichs zu gewährleisten). Es ist etwa 50% langsamer als ungeprüfte Arithmetik (gemäß Profiling).

Das Verschieben des arithmetisch-sensitiven Teils in ein Projekt mit ungeprüfter Arithmetik könnte funktionieren, aber es scheint übertrieben zu sein, eine Assembly ganz für sich selbst zu erstellen.

+1

Eine zusätzliche C# -Assembly ist möglicherweise übertrieben, aber Sie können auch ein Modul aus der C# -Datei (einige Befehlszeilenparameter für den Compiler) erstellen und dann ILmerge verwenden, um es mit Ihrer VB.NET-Assembly zu verbinden. – OregonGhost

Antwort

2

Persönlich denke ich, dass es eine gute Option ist, dies in einer eigenen Baugruppe zu belassen, vor allem, weil es so eine kleine Baugruppe sein wird. Dies erleichtert die Wartung, da diese Baugruppe jederzeit problemlos regeneriert werden kann. Machen Sie einfach eine separate Assembly, die nicht markiert ist, und geben Sie Ihren leistungsabhängigen Code dort ein.

+0

Sie können ungeprüfte Arithmetik in VB ausführen. Das Problem ist, dass es sich um eine projektweite Option handelt (unter Erweiterte Kompilieroptionen auf der Registerkarte Kompilieren). –

+0

@Strilanc: Noch besser - bearbeitet meine Antwort dann. Ich würde nur ein separates Projekt für Ihre Perf. Machen. kritischer Code, und referenzieren Sie es dann. –

+4

Ich habe etwas etwas anderes gemacht: Ich schrieb Typen mit ungeprüfter Arithmetik und legte diese in die ungeprüfte Assembly. Jetzt habe ich ModByte/ModInt16/ModInt32/ModInt64 und die ungeprüfte Assembly wird definitiv nicht langsam Code absorbieren. –

3

Ich weiß, das ist alt, aber ich musste vor kurzem einige C# -Code konvertieren, die unchecked verwendet und ich dachte, ich würde teilen, wie ich es getan habe. Es ist reiner VB-Code und kann beliebig skaliert werden (anstatt einer projektweiten Option).

Der Trick besteht darin, eine Struktur zu erstellen, die ein Long-Feld und zwei Integer-Felder enthält. Verwenden Sie dann die Attribute StructLayout und FieldOffset, um eine Vereinigung der langen und der beiden Ganzzahlen zu erstellen. Die Felder können (sollten) privat sein. Verwenden Sie zum Erweitern von CType-Operatoren die Konvertierung von Long in die Struktur und von der Struktur in Integer (unter Verwendung des niedrigen Integer-Werts). Fügen Sie Operatorüberladungen für +, -, * usw. hinzu ... und presto! ungeprüfte Arithmetik in VB!

Sortieren ... es wird immer noch überlaufen, wie Strilanc darauf hingewiesen hat, wenn der lange Wert außerhalb des Bereichs für Longs geht. Aber es funktioniert ziemlich gut für viele Situationen, in denen nicht geprüft wird.

Hier ist ein Beispiel:

<StructLayout(LayoutKind.Explicit)> 
Public Structure UncheckedInteger 

    <FieldOffset(0)> 
    Private longValue As Long 
    <FieldOffset(0)> 
    Private intValueLo As Integer 
    <FieldOffset(4)> 
    Private intValueHi As Integer 

    Private Sub New(newLongValue As Long) 
     longValue = newLongValue 
    End Sub 

    Public Overloads Shared Widening Operator CType(value As Long) As UncheckedInteger 
     Return New UncheckedInteger(value) 
    End Operator 

    Public Overloads Shared Widening Operator CType(value As UncheckedInteger) As Long 
     Return value.longValue 
    End Operator 

    Public Overloads Shared Widening Operator CType(value As UncheckedInteger) As Integer 
     Return value.intValueLo 
    End Operator 

    Public Overloads Shared Operator *(x As UncheckedInteger, y As Integer) As UncheckedInteger 
     Return New UncheckedInteger(x.longValue * y) 
    End Operator 

    Public Overloads Shared Operator Xor(x As UncheckedInteger, y As Integer) As UncheckedInteger 
     Return New UncheckedInteger(x.longValue Xor y) 
    End Operator 

    ' Any other operator overload you need... 
End Structure 

die Struktur im Code verwenden wie folgt aus:

Dim x As UncheckedInteger = 2147483647 
Dim result As Integer = x * 2 ' This would throw OverflowException using just Integers 

Console.WriteLine(result.ToString()) ' -2 

Sorgfältige, dass Ihre Berechnungen Überlauf nicht, bevor das Ergebnis zu einem UncheckedInteger zuweisen. Sie können UncheckedShort- und UncheckedByte-Strukturen mit derselben Technik erstellen.

+0

Wird das nicht irgendwann noch überlaufen? Was passiert, wenn man mit zwei multipliziert, bis auch die Reichweite der langen überschritten wird? –

+0

Der Code, wie ich es postete, würde sicherlich überlaufen, wenn der lange Wert außerhalb seines Bereichs ging. In meiner Situation musste ich mir deswegen keine Sorgen machen.Wenn ein Überlauf des langen Werts ein Problem darstellt, könnte man jederzeit Bereichsüberprüfungen hinzufügen. –

Verwandte Themen