Поддерживать биты при преобразовании из UInt32 в Int32 - PullRequest
0 голосов
/ 16 марта 2020

Мне нужно отобразить координаты (строка, столбец), которые являются положительными целочисленными значениями. Я реализую .GetHashCode следующим образом:

    Public Function GetHashCode As Integer
            If _HashCode Is Nothing Then
                Const BitsPerValue As Integer = 32 \ 2
                Dim UnsignedCode As UInt32 = CType(Me.Row, UInt32) Xor (CType(Me.Column, UInt32) << BitsPerValue)
                _HashCode = CType(UnsignedCode, Int32)
            End If
            Return _HashCode.Value
    End Function
    Private _HashCode As Integer?

Примечание Me.Row >= UInt16.MinValue And Me.Row <= UInt16.MaxValue и то же самое относится к .Column.

Производительность является ключевой . Я не против, что такое HashCode. Я считаю, что оптимальное преобразование из UInt32 в Int32 не должно изменять биты в памяти. Но я обеспокоен, потому что это, вероятно, то, что происходит, поскольку обе следующие строки возвращают одно и то же значение:

    Dim Unsigned123 As UInt32 = 123
    Dim Unsigned456 As UInt32 = 456
    Console.WriteLine("(UInt32) 123 Xor (456 << 16) = " & CType(Unsigned123 Xor (Unsigned456 << 16), UInt32))
    Console.WriteLine("(Int32) 123 Xor (456 << 16) = " & CType(Unsigned123 Xor (Unsigned456 << 16), Int32))

Как я могу привести, не изменяя биты в памяти? Я понимаю, что выражение unchecked() в C# было бы идеальным здесь, но оно не доступно для VB. Net.

Я мог бы использовать BitConverter.ToInt32(BitConverter.GetBytes(UnsignedCode), 0), но разве это не жадная операция?

Это в основном противоположный вопрос этого , где я бы хотел бы 3392918397 стать -902048899

1 Ответ

0 голосов
/ 16 марта 2020

Ожидается, что приведение двух целых чисел от одного типа к другому вернет одно и то же значение (оба по битам - по основанию 10), как только они не переполнятся.

Примите во внимание следующее:

    Dim SignedMin As Int32 = Int32.MinValue
    Dim SignedMax As Int32 = Int32.MaxValue
    Dim UnsignedMin As UInt32 = UInt32.MinValue
    Dim UnsignedMax As UInt32 = UInt32.MaxValue

    Console.WriteLine("SignedMin As UInt32 = " & BitConverter.ToString(BitConverter.GetBytes(CType(SignedMin, UInt32)))) 'OverflowException
    Console.WriteLine("SignedMax As UInt32 = " & BitConverter.ToString(BitConverter.GetBytes(CType(SignedMax, UInt32)))) 'FF-FF-FF-7F
    Console.WriteLine("UnsignedMin As UInt32 = " & BitConverter.ToString(BitConverter.GetBytes(CType(UnsignedMin, UInt32)))) '00-00-00-00
    Console.WriteLine("UnsignedMax As UInt32 = " & BitConverter.ToString(BitConverter.GetBytes(CType(UnsignedMax, UInt32)))) 'FF-FF-FF-7F

    Console.WriteLine("SignedMin As Int32 = " & BitConverter.ToString(BitConverter.GetBytes(CType(SignedMin, Int32)))) '00-00-00-80
    Console.WriteLine("SignedMax As Int32 = " & BitConverter.ToString(BitConverter.GetBytes(CType(SignedMax, Int32)))) 'FF-FF-FF-7F
    Console.WriteLine("UnsignedMin As Int32 = " & BitConverter.ToString(BitConverter.GetBytes(CType(UnsignedMin, Int32)))) '00-00-00-00
    Console.WriteLine("UnsignedMax As Int32 = " & BitConverter.ToString(BitConverter.GetBytes(CType(UnsignedMax, Int32)))) 'OverflowException

Возвращает

SignedMin As UInt32 = OverflowException
SignedMax As UInt32 = FF-FF-FF-7F
UnsignedMin As UInt32 = 00-00-00-00
UnsignedMax As UInt32 = FF-FF-FF-FF

SignedMin As Int32 = 00-00-00-80
SignedMax As Int32 = FF-FF-FF-7F
UnsignedMin As Int32 = 00-00-00-00
UnsignedMax As Int32 = OverflowException

Операции сдвига битов << и >> выполняют переполнение без исключения. Переполненные биты теряются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...