24- в 32-битное преобразование в Java
Меня интересует новый проект IoT под названием OpenBCI, который в основном представляет собой ЭЭГ с открытым исходным кодом для чтения и обработки мозговых волн и других биоданных. В своих документах они утверждают, что данные, передаваемые по радиоканалу (через RFDuino), отправляют 24-битные данные. Чтобы преобразовать 24-разрядные значения в 32-разрядные целые числа со знаком, они предлагают следующий дружественный к Java код обработки:
int interpret24bitAsInt32(byte[] byteArray) {
int newInt = (
((0xFF & byteArray[0]) << 16) |
((0xFF & byteArray[1]) << 8) |
(0xFF & byteArray[2])
);
if ((newInt & 0x00800000) > 0) {
newInt |= 0xFF000000;
} else {
newInt &= 0x00FFFFFF;
}
return newInt;
}
Думаю, я пытаюсь понять, что именно здесь происходит. Давайте возьмем первый всплеск кода:
int newInt = (
((0xFF & byteArray[0]) << 16) |
((0xFF & byteArray[1]) << 8) |
(0xFF & byteArray[2])
);
- Почему можно предположить, что на входе есть 3 байта?
- Какое значение имеет
0xFF
значение? - Какова цель сдвига влево (
<<
)?
Второй сегмент тоже немного загадочный:
if ((newInt & 0x00800000) > 0) {
newInt |= 0xFF000000;
} else {
newInt &= 0x00FFFFFF;
}
- Зачем
newInt & 0x00800000
? Какое значение имеет0x00800000
? - Почему
if-else
на основе положительного и неотрицательного результата вышеуказанной операции? - Какое значение имеет
0xFF000000
а также0x00FFFFFF
?
Я думаю, что с этой функцией происходит много волнений и магии, которые я хотел бы понять лучше!
1 ответ
Почему можно предположить, что на входе есть 3 байта?
24 бита / 8 бит = 3 байта
Какое значение имеет значение 0xFF?
Это немного маска. 0b11111111
в двоичном В этой ситуации это используется как быстрый способ преобразовать значение байта в int.
Какова цель сдвига влево (<<)?
Как только значение int было получено в предыдущей инструкции, оно сдвигается на 16 бит влево, чтобы занять позицию третьего байта целого числа (считая справа). Это связано с тем, что байтовый массив хранит байты в формате с прямым порядком байтов, где MSB стоит первым. Следующий байт сдвигается только на 8 бит, чтобы занять позицию второго байта, и последний не нужно сдвигать вообще, поскольку он уже находится в первой позиции байта.
Почему newInt & 0x00800000? Каково значение 0x00800000?
Что ж 0x80
это другая битовая маска для получения MSB определенного байта. 0x00800000
соответствует старшему биту третьего байта (т.е. байту в byteArray[0]
это было сдвинуто на 16 бит в предыдущем процессе). Это также соответствует MSB всего 24-битного значения.
Почему if-else основан на положительном и неотрицательном результате вышеуказанной операции?
Определение, является ли MSB 24-битного значения 1 или 0, скажет нам, является ли это отрицательным или положительным числом, соответственно, в двоичной записи дополнения.
Каково значение 0xFF000000 и 0x00FFFFFF?
Если число является отрицательным в его 24-битном представлении, мы также хотим, чтобы оно было отрицательным как 32-битное значение в дополнении к двум, поэтому мы должны заполнить 4-й и последний байт 0b11111111
(0xFF) используя оператор OR.
Если он уже был положительным, то четвертый байт может быть 0x00, при этом следующие 3 байта совпадают с исходным 24-битным значением, что достигается маскированием с помощью 0x00FFFFFF
,