VB.NET Преобразование 4 байтов в целое число

Windows 11 США.

VB.NET, Как преобразовать 4 байта массива байтов в целочисленное значение?

Я могу понять, как сделать два байта, используя что-то вроде

IntValue = (mybyte(0) * 256) Or mybyte(1)

Итак, если mybyte(0) = 3 и mybyte(1) = 232 или шестнадцатеричный эквивалент 03E8, это будет int=1000.

Как я могу это сделать, если у меня есть 4 байта? mybyte(0)..(3).

Итак, если бы у меня было myByte(0) = 64, а остальные байты (x) равны 0 или шестнадцатеричному эквивалентному числу 40000000, это было бы равно 1 073 741 824.

Я попробовал другие предложения:

intval = Bitconverter.Toint32(mybyte, 0)

... все, что я получаю, это 64.

я тоже попробовал

Dim combined As UInteger = CType(((mybyte(0) << 24) Or (mybyte(1) << 16) Or (mybyte(2) << 8) Or (mybyte(3) << 0)), UInteger)

... все, что я получаю, это 64

ожидаю 1 073 741 824

Этот вопрос похож на: Преобразование 16-битного регистра в два 8-байтовых с использованием vb.net в Visual Studio. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.

It all makes cents 28.08.2024 19:02

Может быть, вы могли бы заполнить массив в обратном порядке?

Andrew Morton 28.08.2024 19:07

Повторно добавлен тег C#. Первоначально ОП добавил его, и поэтому я предположил, что решение C# жизнеспособно (поскольку ОП предположительно может преобразовать его в VB.NET на основе их исходных тегов) и опубликовал соответствующий ответ.

wohlstad 28.08.2024 19:12

Я пометил это как дубликат, но пропустил, что уже была попытка использовать BitConverter и получил неправильный результат. Как упоминается в коде ответа от Вольстада (и намекается в комментарии Эндрю Мортона), это похоже на проблему с порядком байтов.

Craig 28.08.2024 19:36

Я не дал ответа, потому что 1) пост, который я упомянул в своем предыдущем комментарии, содержит хорошее объяснение побитовых операций, 2) у меня не было времени, 3) я не знал, что будет такая большая конкуренция дайте ответ (кто не любит хорошую конкуренцию)

It all makes cents 28.08.2024 20:22

@Itallmakescents Часто бывает интересно, что, казалось бы, простые вещи требуют дополнительных исследований. Например, освежить в памяти, что оператор << не расширяет результат.

Andrew Morton 28.08.2024 20:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
57
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Поскольку вы также изначально пометили теги C# (до того, как теги были отредактированы), вот решение на C# (которое, я предполагаю, вы можете легко преобразовать в VB.NET).

Использование BitConverter, о котором вы упомянули, действительно является правильным решением.

Следующий пример основан на документации MS: Как преобразовать массив байтов в int:

byte[] bytes = new byte[] { 64, 0, 0, 0 };

// If the system architecture is little-endian (that is, little end first),
// reverse the byte array.
if (BitConverter.IsLittleEndian)
    Array.Reverse(bytes);

int i = BitConverter.ToInt32(bytes, 0);
Console.WriteLine("int: {0}", i);

Выход:

int: 1073741824

Обратите внимание на правильную обработку Endianness, чтобы убедиться, что байты обрабатываются в правильном порядке.

Live demo

В этом и была проблема: мне пришлось перевернуть массив, чтобы получить правильный ответ. Спасибо всем откликнувшимся за помощь. Некоторые примеры других авторов также помогли лучше понять проблему.

Ken Taylor 28.08.2024 21:44

@KenTaylor рад помочь и спасибо, что принял мой ответ. На всякий случай, если вы не в курсе, вы также можете проголосовать за мой ответ и любой другой полезный ответ (голосование и принятие — это отдельно). См.: Что мне делать, если кто-то отвечает на мой вопрос?.

wohlstad 28.08.2024 22:12

В ВБ,

    Dim i As Integer
    Dim byts() As Byte = {1, 2, 3, 255}
    If BitConverter.IsLittleEndian Then
        Array.Reverse(byts)
        i = BitConverter.ToInt32(byts, 0) ' i = 16909311
    Else
        i = BitConverter.ToInt32(byts, 0) ' i = -16580095
    End If

Надеюсь, это поможет.

Другой подход...

    Dim byts() As Byte = {1, 2, 3, 255}
    If Not BitConverter.IsLittleEndian Then
        Array.Reverse(byts)
    End If
    Dim i As Integer = 0
    For Each b As Byte In byts
        i = i << 8
        i = i Or b
    Next

Когда элементы mybyte имеют тип Byte, выполнение mybyte(0)) << 24 приводит к созданию Byte, что нехорошо, поскольку все биты теряются. Этот оператор дает результат того же типа, что и левый операнд.

Вам нужно преобразовать каждый элемент в тот тип, который вы хотите получить в конце:

Dim a = CUInt(mybyte(0)) << 24 Or CUInt(mybyte(1)) << 16 Or CUInt(mybyte(2) << 8) Or mybyte(3)

(Арифметический битовый сдвиг имеет более высокий приоритет, чем побитовые операторы. Последний байт не нужно преобразовывать в другой тип.)

Была некоторая несогласованность в вопросе о том, нужно ли целое число или целое число без знака: измените вхождение CUInt на CInt, если первое.

Если вы используете операторы * и +, вы можете сделать

Dim b = (((mybyte(0) * 256 + mybyte(1)) * 256) + mybyte(2)) * 256 + mybyte(3)

или

Dim c = mybyte(0) * 16777216 + mybyte(1) * 65536 + mybyte(2) * 256 + mybyte(3)

которые работают без преобразований, поскольку множители 16777216, 65536 и 256 имеют тип Integer.

Или вы можете просто использовать:

Dim n = BitConverter.ToInt32(mybyte.Reverse().ToArray(), 0)

Наконец, если вы используете .NET Core 2.1 или новее, это очень просто:

Dim d = BinaryPrimitives.ReadInt32BigEndian(mybyte)

Документы: Класс BinaryPrimitives «Используйте эти помощники, когда вам нужно прочитать конкретный порядок байтов».

Другие вопросы по теме