pronto писал(а):Нужно каждое десятичное число записать 4-мя битами.
'Упаковка (на входе число в переменной i As Long
P& = "&H" + LTrim$(i&)
'Распаковка (на выходе текст в переменной s As String)
s$ = Hex(P&)
Есть число A = 12345678. Оно хранится в целочисленной переменной с типом Long.
Двоичное представление этого числа вот такое:
ValueToBin(12345678) = "0000 0000 1011 1100 0110 0001 0100 1110"
Есть второе число B. Оно тоже имеет целочисленный тип.
Чтобы A преобразовать в нужный формат, достаточно преобразовать A в строку
и заодно удалить пробел спереди
B = "&H" + LTrim$(A)
В переменной В окажется число 305419896
Двоичное представление этого числа вот такое:
ValueToBin(305419896) = "0001 0010 0011 0100 0101 0110 0111 1000"
теперь в каждых 4-х битах B по одной цифре: 1 2 3 4 5 6 7 8
0 1 2
0000 0000 0000 0000 0000 0000 0000 0000|0000 0000 0000 0000 0000 0000 0000 0000|0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000|0000 0000 0000 0000 0000|0000 0000 0000 0000 0000|0000 0000 0000 0000 0000|0000 0000 0000 0000
0 1 2 3
0000 0000|0000 0000|0000 0000|0000 0000|0000 0000|0000 0000|0000 0000|0000 0000|0000 0000|0000 0000|0000 0000|0000 0000
0 1 2 3 4 5 6 7 8 9 10 11
pronto писал(а):Это всё распрекрасно!
Теперь к этим знаниям присоедини знание о работе логических операций (AND, OR). Попробуй с их помощью записать 20 младших бит в переменную типа Long. Задача из двух действий.
bitpart& = (v& and 12) \ 4
bitpart& = (v& and 12) \ 4
Чтобы сдвинуть биты вправо на N позиций, то нужно число разделить на 2^N.
Чтобы сдвинуть биты влево на N позиций, то нужно число умножить на 2^N.
Например, хочу сдвинуть биты в числе 5616 на 4 позиции вправо.
2^4 (2 в степени 4) = 16
5616 / 16 = 351
v& and 12 = 0000 1100
\ 4 = 000000 11
v& = v& or 1 ' установлен бит под номером 0
v& = v& and (not 64) ' сбросить бит 6
C1CB54 0000 0000 1100 0001 1100 1011 0101 0100
v& = v& and (not 12) ' сбросить бит 2 и 3
v& = v& and 12
354 0000 0000 0000 0000 0000 0011 0101 0100
Сумма степени группы бит = следующему биту в степени -1
2^16-1
Don Leno писал(а):битовые операции это темный лес)))) Так что pronto мне просто помогает освоиться с ними... В свою очередь чтобы ему было понятны мои рассуждения я их и пишу)))
Don Leno писал(а):В итоге для того чтобы посчитать чему равна сумма степени битов с 8-15 (средние 8 младших бит) нужно:
2^16-1
Верно ли предположил?
Ubit = 15: LBit = 8
S = (2 ^ (Ubit + 1) - 1) And (Not 2 ^ LBit - 1)
S=(2^(15+1)-1) and (not 2^8-1)
S=(65535) and (not 255)
1111 1111 0000 1111
1. S=(2^16-1) And ((Not 2^8-1) And (2^4-1))
2. S=((2^16-1) And (Not 2^8-1)) And (2^4-1)
Это сброс всех бит, кроме 2 и 3 бита
- Код: Выделить всё
v& = v& and 12
S=( ((2^16-1)/16) And (Not 2^4-1) )*16
Don Leno писал(а):Применимы ли битовые операции к массивам??
Don Leno писал(а):Я иногда не понимаю как And работает
И еще вопрос: как считать биты 0-3 и 8-15??
S=( ((2^16-1)/16) And (Not 2^4-1) )*16
0 1 2 - индекс?
0000 0010 1110 1010 1111 0000
Don Leno писал(а):И еще вопрос: как считать биты 0-3 и 8-15??
S=( ((2^16-1)/16) And (Not 2^4-1) )*16
- это правильно?
Don Leno писал(а):Val/16 - логический сдвиг?
Как выполнить арифметический сдвиг?
Как выполнить циклический сдвиг?
Don Leno писал(а):смело брать массив
Don Leno писал(а):К примеру массив Ar(2) as Byte будет выглядить так(?):
Ar(0) = 2
Ar(1) = 234
Ar(2) = 240
Private Data() As Long, DataExist As Boolean
Private Declare Sub GetMem4 Lib "msvbvm60" (ByVal Addr As Long, Retval As Long)
Private Declare Sub PutMem4 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Long)
' для чтения
Private Const ZeroOut_00FFFFF0 As Long = &HFFFFF0
Private Const ZeroOut_000FFFFF As Long = &HFFFFF
' для записи
Private Const ZeroOut_FF00000F As Long = &HFF00000F
Private Const ZeroOut_FFF00000 As Long = &HFFF00000
ReDim Data(Int(60 * 5 / 8)) ' 60 - количество 20-битных чисел
Private Sub PutNumber_v2(ByVal NumberIdx As Long, ByVal NumberVal As Long)
Dim ByteIndex As Long, DataNumber As Long
' VarPtr(Data(0)) - указатель на начало данных
ByteIndex = VarPtr(Data(0)) + Int(NumberIdx * 5 / 2)
GetMem4 ByteIndex, DataNumber
' так совпало (числа занимают 2,5 байта!), что начало числа с чётным индексом попадает
' на начало байта, а начало числа с нечётным индексом — на середину байта
' проверка нулевого бита даёт проверку на чётность, так как он задаёт разницу
' между чётным и нечётным числом.
If NumberIdx And 1 Then
' начало числа приходится на середину байта
' 1. Подготовить место под новое значение путём обнуления бит 4 - 23.
DataNumber = DataNumber And ZeroOut_FF00000F
' 2. Новое значение сдвинуть на 4 бита влево
NumberVal = NumberVal * &H10
'
Else
' начало числа приходится на границу байта
' Подготовить место под новое значение путём обнуления бит 0 - 19.
DataNumber = DataNumber And ZeroOut_FFF00000
End If
' Объединить данные из массива с новым значением
DataNumber = DataNumber Or NumberVal
' записать новое значение в массив
PutMem4 ByteIndex, DataNumber
End Sub
Private Function GetNumber_v2(ByVal NumberIdx As Long) As Long
'Dim ByteIndex As Long
' вычисление адреса байта, на который приходится начало 20-битного числа
'ByteIndex = Int(Val(NumberIdx) * 5 / 2) ' 5 и 2 получены после сокращения 20 и 8
' чтение 4-х байт.
'GetMem4 VarPtr(Data(0)) + ByteIndex, GetNumber_v2
GetMem4 VarPtr(Data(0)) + Int(NumberIdx * 5 / 2), GetNumber_v2
If NumberIdx And 1 Then
' начало числа приходится на середину байта
' 1. Обнулить биты с 0-го по 3-й и с 24-го по 31-й включительно
' &HFFFFF0 - маска для соответсвующих бит (0000 0000 1111 1111 1111 1111 1111 0000)
' Именно она задаёт, какие биты оставить, а какие сбросить.
' Если в маске бит = 1, то в результате он остаётся.
' Это вытекает из таблицы истинности оператора AND (Конъюнкция)
' V M R (V - переменная, M - маска, R - результат)
' 0 AND 0 = 0
' 0 AND 1 = 0
' 1 AND 0 = 0
' 1 AND 1 = 1
' 2. Сдвинуть на 4 бита вправо
GetNumber_v2 = (GetNumber_v2 And ZeroOut_00FFFFF0) \ &H10
Else
' начало числа приходится на границу байта
' 1. Обнулить биты с 20-го по 31-й включительно
GetNumber_v2 = GetNumber_v2 And ZeroOut_000FFFFF
End If
End Function
Сейчас этот форум просматривают: AhrefsBot, Google-бот, Yandex-бот и гости: 27