Dot-Net

在 VB.Net 中進行未經檢查的整數加法的最快方法?

  • April 25, 2020

我有一個項目,我想預設檢查算術,除了一個性能敏感點。不幸的是,VB.Net 沒有“未檢查”塊。

理想情況下,該框架將具有某種帶有明確未經檢查的算術的整數類型,但我沒有找到類似的東西。我確實發現表達式樹具有用於未經檢查的操作的二進製表達式,但委託成本抵消了未經檢查的優勢(然後是一些)。

目前,我在進行算術運算之前將輸入轉換為 UInt64/Int64,然後再轉換回來(使用按位 And 以確保在範圍內)。它比未經檢查的算術(根據分析)慢約 50%。

將算術敏感部分移動到具有未經檢查的算術的項目中可能會起作用,但是將其全部單獨提供給它似乎有點過頭了。

就個人而言,我認為將它留在自己的程序集中,特別是因為它是一個如此小的程序集,是一個不錯的選擇。這使得維護更容易,因為隨時可以輕鬆地重新生成此組件。只需將一個單獨的程序集標記為未選中,然後將您的性能敏感程式碼放在那裡。

我知道這很舊,但我最近需要轉換一些未經檢查的 C# 程式碼,我想我會分享我是如何做到的。它是純 VB 程式碼,可以根據需要調整範圍(而不是項目範圍的選項)。

訣竅是創建一個包含一個 Long 欄位和兩個 Integer 欄位的結構。然後使用 StructLayout 和 FieldOffset 屬性來創建 long 和兩個整數的並集。這些欄位可以(應該)是私有的。使用擴展 CType 運算符從 Long 轉換為結構,從結構轉換為 Integer(使用低整數值)。為 +、-、* 等添加運算符重載……然後!VB中未經檢查的算術!

有點……它仍然會溢出,正如 Strilanc 指出的那樣,如果 long 值超出 long 的範圍。但它適用於許多使用 unchecked 的情況。

這是一個例子:

<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

在程式碼中使用如下結構:

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

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

在將結果分配給 UncheckedInteger 之前,請注意您的計算不會溢出。您可以使用相同的技術創建 UncheckedShort 和 UncheckedByte 結構。

引用自:https://stackoverflow.com/questions/2403154