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

1 ответ:

Почему можно с уверенностью предположить, что на входе имеется 3 байта?

24 бита / 8 бит = 3 байта

Какова значимость значения 0xFF?

Это немного маска. 0b11111111 в двоичном коде. В этой ситуации он используется как быстрый способ преобразовать значение байта в int.

Какова цель сдвига левого бита (

Как только значение int было получено в предыдущей инструкции, оно сдвигается на 16 бит влево. занять позицию третьего байта int (считая справа). Это связано с массивом байтов, хранящим байты в форматеbig-endian , где MSB стоит на первом месте. Следующий байт сдвигается только на 8 бит, чтобы занять позицию второго байта, а последний вообще не нужно сдвигать, так как он уже находится в первой точке байта.

Почему newInt & 0x00800000? Каково значение 0x00800000?

Ну 0x80 это еще одна битовая маска чтобы получить MSB определенного байта. 0x00800000 соответствует MSB третьего байта (то есть байта в byteArray[0], который был сдвинут на 16 бит, оставшихся в предыдущем процессе). Это также соответствует MSB всего 24-битного значения.

Почему if-else основан на положительном и неотрицательном результате вышеупомянутой операции?

Определение того, является ли MSB 24-битного значения 1 или 0, покажет нам, является ли оно отрицательным или положительным числом, соответственно, в дополнении two нотация.

Каково значение 0xFF000000 и 0x00FFFFFF?

Если число отрицательно в его 24-битном представлении, мы также хотим, чтобы оно было отрицательным как 32-битное значение в дополнении двух, поэтому мы должны заполнить 4-й и последний байт 0b11111111 (0xFF) с помощью оператора OR.
Если он уже был положительным, то четвертый байт может быть 0x00, при этом следующие 3 байта совпадают с исходным 24-битным значением-выполняется маскировка с помощью 0x00FFFFFF.