繁体   English   中英

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

[英]Fastest way to do an unchecked integer addition in VB.Net?

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

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

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

将算术敏感部分移到具有未经检查的算术的项目中可能会奏效,但将其全部归于自己的程序集似乎有些过分。

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

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

有点......它仍然会溢出,正如Strilanc指出的那样,如果long值超出longs的范围。 但它在很多使用 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 结构。

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

我最近在 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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM