#vb.net #types #type-conversion
#vb.net #типы #преобразование типов
Вопрос:
У меня есть 32-разрядное значение, которое хранится в VB.Тип Net Integer (т.е. Int32.) Меня интересуют только биты, а не числовое значение. Иногда 32-й бит интерпретируется как отрицательное число. Моя цель — изменить фактические биты. Мои исходные данные кодируются в биты справа налево (LSB самый правый) и считываются обратно слева направо (MSB самый левый). Я адаптирую чужой код и дизайн. У меня была мысль, возможно, временно преобразовать в long, но я не знаю, как это сделать и правильно сохранить 32-й бит.
Public Shared Function ReverseBits32(ByVal n As Integer) As Integer
Dim result As Integer = 0
For i As Integer = 0 To 32 - 1
result = result * 2 n Mod 2
n = n >> 1 'n Or 2
Next
Return result
End Function
Комментарии:
1. Если вас интересует только бит, почему вы используете целое число со знаком?
2. Я начал с примера приложения, которое изначально работало с 8-разрядными значениями, но было реализовано с использованием 32-разрядных целых чисел. Это имеет смысл, поскольку это будет иметь гораздо более высокую производительность. Для моего использования требуются 32-разрядные значения. Это сильно задержало бы мой проект, если бы я попытался преобразовать типы данных на этом этапе. Я отредактирую вопрос, чтобы более точно объяснить мое требование.
3. Это не позволит мне редактировать. Итак, мне нужна функция для полного изменения битов в 32-разрядном целом числе со знаком. Я отключаю 32-й бит, когда он равен единице, тем самым делая его отрицательным числом.
4. Итак, что вам на самом деле нужно, это просто способ поменять местами биты в 32-разрядном целом числе, и с этим у вас проблемы? Вам вовсе не обязательно переходить к 64 битам, если есть какой-то другой способ обратить 32 бита вспять?
5. Да, извините, я не выразился яснее.
Ответ №1:
Если бы у вас был метод обратного преобразования битов байта, вы могли бы применить его четыре раза к байтам целого числа. Небольшое исследование выявило хаки с подменой бит.
Module Module1
Sub ShowBits(a As Integer)
Dim aa = BitConverter.GetBytes(a)
Console.WriteLine(String.Join(" ", aa.Select(Function(b) Convert.ToString(b, 2).PadLeft(8, "0"c))))
End Sub
Function ReverseBits(b As Byte) As Byte
' From https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
Dim c = CULng(b)
Return CByte((((c * amp;H802UL And amp;H22110UL) Or (c * amp;H8020UL And amp;H88440UL)) * amp;H10101UL >> 16) And amp;HFFUL)
End Function
Function ReverseBits(a As Integer) As Integer
Dim bb = BitConverter.GetBytes(a)
Dim cc(3) As Byte
For i = 0 To 3
cc(3 - i) = ReverseBits(bb(i))
Next
Return BitConverter.ToInt32(cc, 0)
End Function
Sub Main()
Dim y = -762334566
ShowBits(y)
y = ReverseBits(y)
ShowBits(y)
Console.ReadLine()
End Sub
End Module
Вывод из тестового значения:
10011010 10110010 10001111 11010010
01001011 11110001 01001101 01011001
Я использовал метод «no 64-bit», потому что он написан для языка, где арифметическое переполнение игнорируется — методы, использующие 64-разрядные операции, полагаются на это, но это не используется по умолчанию для VB.NET.
Комментарии:
1. Мне потребуется некоторое время, чтобы разобраться, но я предполагаю, что «CByte ((((c * amp; H802UL И amp;H22110UL) Или (c * amp; H8020UL И amp;H88440UL)) * amp;H10101UL >> 16) И amp; HFFUL)» обрабатывает бит знака? Это выглядит многообещающе.
2. Байт без знака.
BitConverter.GetBytes
получает необработанные байты без какой-либо интерпретации. Таким образом, знаковый бит в него не входит 🙂