Написание функции: короткие GetBits (короткие данные, int p, int n) - PullRequest
1 голос
/ 30 июня 2009

Я пишу функцию short getBits (короткие данные, int p, int n)

Я пробовал:

public static short getBits(short data, int p, int n) {
    short bitmask = (short) ((~0 << (16 -n)) >>> p);
    short returnVal = (short) ((bitmask & data) >>> (16 - n));
    return returnVal;
}

Это работает для getBits ((short) 0x7000, 0, 4), но если я заменил 7 на 8, я получу отрицательное значение.

Ответы [ 2 ]

2 голосов
/ 30 июня 2009

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

Я предполагаю, что вы используете переменные типа int из-за отсутствия явных приведений в выражении. Если вы используете тип int для своих переменных: data start_pos и length; вы должны использовать 32 вместо 16, так как int являются 32-битными значениями.

Также, если вы собираетесь использовать целочисленные примитивные типы, такие как int, short или byte, помните, что эти примитивные типы являются дополнением к двум, которые расширяются до знака, что означает, что если вы сделаете правильный сдвиг на отрицательных числах, таких как ~ 0 ( оценивается как -1), те будут добавлены к биту высшего порядка (знаковый бит) вместо нулей.

Например:

1111 1111 1111 1111 1111 1111 1111 1000        
>>1
1111 1111 1111 1111 1111 1111 1111 1100 

Теперь вернемся к вашей проблеме. Общая идея заключается в том, чтобы уметь:

data & mask

Теперь генерация маски немного сложна для подписанных типов данных. Имеет смысл сгенерировать маску, используя:

(~0 << (32 - length) >> (32 - length - start_pos))

Но это, конечно, не сработает из-за расширения знака.

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

Например:

1111 1111 1111 1111 1111 1111 1111 1000        
>>>1
0111 1111 1111 1111 1111 1111 1111 1100 

так ... * * 1023

mask = (~0 << 32-length >>> 32-length-start_pos)

И ваш окончательный ответ будет выглядеть примерно так:

(data & (~0 << 32-length >>> 32-length-start_pos)) >>> start_pos

Операция внешнего поворота перемещает ваши замаскированные данные в младшие биты.

1 голос
/ 01 ноября 2009

Не уверен, почему нужно использовать шорт. Вот решение с использованием long.

public static long getBits(long data, int p, int n) {
    assert p >= 0 && p < 64;
    assert n >= 0 && n < 64;
    return (data >> p) & ((1 << n) - 1);
}
...