Java: Как создать метод для извлечения расщепленных битов целочислений из байтового массива с помощью маски

StackOverflow https://stackoverflow.com/questions/3176705

  •  02-10-2019
  •  | 
  •  

Вопрос

Работая над декодированием некоторых стандартов потоковых видео, я заметил много экземпляров, где биты целочисленного значения предоставляются в чем-либо от 2-6 байтов, но, разделенные зарезервированными битами следующим образом:

// Specification (16 bits)
// -----------------------
// Reserved         1  bit
// Value A [6-7]    2  bit
// Reserved         2  bit
// Value A [4-5]    2  bit
// Reserved         3  bit
// Value A [0-3]    4  bit
// Reserved         2  bit

Например, значение 185 (10111001 или 0xB9) будет храниться следующим образом в двух байтовом массиве:

01000110 00100100

Я знаю, что это гайки, но именно так, как эти парни закодировали свой поток данных. Это может быть извлечено, используя следующие битные операции

int w = 0;
w |= (0x60 & data[0]) >>> 5;  // extract the first 2 bits shifted to the front
w <<= 2;                      // bump them up 2 bits for the next section
w |= (0x06 & data[0]) >>> 1;  // extract the next 2 bits shifted to the front
w <<= 4;                      // bump them up 4 bits for the last section
w |= (0x3C & data[0]) >>> 2;  // extract the last 4 bits shifted to the front

// w now will equal 10111001 (185)

То, что я хотел бы сделать, это сделать, это создать метод, который примет, что примет байтовый массив неопределенной длины и int, представляющий маску битов, которые соответствуют значению, которое мы пытаемся извлечь, вытекающие из предоставленной спецификации. Что-то вроде этого

public static void testMethod() {

    byte[] data = new byte[] {0x46, 0x24}; // 01000110 00100100 
    int mask = 0x663C;                     // 01100110 00111100
    int x = readIntFromMaskedBytes(data, mask);

}

public static int readIntFromMaskedBytes(byte[] data, int mask) {
    int result = 0;

    // use the mask to extract the marks bits from each
    // byte and shift them appropriately to form an int

    return result;
}

Я закончил проект, который я работал над использованием оригинального «ручного» подхода, но я не удовлетворен тем, что он такой же чистый, как могло бы быть из-за чистого количества этих вхождений и их сложности. Я хотел бы придумать более общий метод, который мог бы достичь одно и то же.

К сожалению, я все еще новичок, когда дело доходит до этой сложности битовой смещения, и я надеялся, что кто-то может предоставить некоторые советы или предложения о том, как лучше всего сделать.

К кселе

Примечание. - Извините любые синтаксические ошибки в псевдокоде выше, это только дизайн, чтобы служить объяснением случая использования.

Это было полезно?

Решение

На самом деле, я склонен думать, что встроенная маска и подход к смещению (если он реализован немного более чисто, чем ваш псевдокод) лучше, чем пытаться написать метод общего назначения. Для опытного разработчика низкоуровневого битового кода Bashing, код чтения кода Mask и Shift не должен быть проблем. Проблема с методом общего назначения вдоль линий, которые вы предлагаете, заключается в том, что он будет значительно менее эффективным ... и сложно для оптимизации JIT Compiler для оптимизации.

Кстати, вот как я бы написал код.

// extract and assemble xxxx from yyyy 
int w = ((0x003C & data[0]) >> 2) | 
        ((0x0600 & data[0]) >> 6) | 
        ((0x6000 & data[0]) >> 7);

РЕДАКТИРОВАТЬ

Я все равно хотел бы понимать, как такой общий подход может быть закодирован, хотя и учебное упражнение.

Что-то вроде этого:

public static int readIntFromMaskedBytes(int data, int mask) {
    int result = 0;
    int shift = 0;
    while (mask != 0) {
        if (mask & 1) {
            result |= (data & 1) << shift++;
        }
        data >>>= 1;
        mask >>>= 1;
    }
}

Как видите, это займет до 32 петлевых итераций, чтобы дать вам ответ. Для вашего примера я бы сказал, что этот подход примерно в 10 раз медленнее, чем оригинальная версия.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top