在VB.Net中进行未经检查的整数加法的最快方法?

时间:2010-03-08 17:14:39

标签: .net vb.net math unchecked

我有一个项目,我想默认检查算术,除了一个性能敏感点。不幸的是,VB.Net没有“未经检查”的阻止。

理想情况下,框架会有一些带有显式未经检查算术的整数类型,但我没有找到类似的东西。我确实发现表达式树有未经检查的操作的二进制表达式,但委托开销取消了未经检查的优势(然后是一些)。

目前我在进行算术运算之前将输入转换为UInt64 / Int64,然后转换回(使用按位并确保范围内)。它比未经检查的算术慢了约50%(根据分析)。

将算术敏感部分移动到具有未经检查算术的项目可能会起作用,但是为它自己提供一个程序集似乎有些过分。

3 个答案:

答案 0 :(得分:5)

我知道这是旧的,但我最近需要转换一些未经检查的C#代码,我想我会分享我是如何做到的。它是纯VB代码,可以根据需要设置范围(而不是项目范围的选项)。

诀窍是创建一个包含Long字段和两个Integer字段的结构。然后使用StructLayout和FieldOffset属性创建long和两个整数的并集。这些字段可以(应该)是私有的。使用扩展的CType运算符从Long转换为结构,从结构转换为Integer(使用低整数值)。为+, - ,*等添加运算符重载...并且presto! VB中未经检查的算术!

排序......它仍会溢出,正如Strilanc指出的那样,如果长值超出了多头的范围。但是对于许多未经检查的情况,它的效果非常好。

以下是一个例子:

<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结构。

答案 1 :(得分:2)

就我个人而言,我认为将其留在自己的装配中,特别是因为它将是如此小的装配,是一个不错的选择。这使维护更容易,因为它可以随时轻松地重新生成该组件。只需将未标记的单独程序集标记,并将性能敏感的代码放在那里。

答案 2 :(得分:0)

我最近在VB.NET中为未检查的整数操作创建了一个nuget包,请参见nuget包VBMath.Unchecked或Github存储库System.Runtime.Extensions.Unchecked

Using System.Numerics

' this will not throw
Dim value = UncheckedInteger.Add(Integer.MaxValue, 1)