Написание функции:короткие GetBits (короткие данные, int p, int n)
Вопрос
Я пишу функцию short getBits(short data, 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, я получил бы отрицательное значение.
Решение
Чтобы все заработало, нужно помнить несколько вещей о типах данных Java.
Я предполагаю, что вы используете переменные типа int из-за отсутствия явного приведения типов в вашем выражении.Если вы используете тип int для своих переменных:данные start_pos и длина;вам следует использовать 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))
Но это, конечно, не сработает из-за расширения знака.
Я бы предложил вместо использования сдвига вправо >> использовать оператор поворота >>> таким образом, вместо добавления битов более высокого порядка, оператор поворота добавит бит младшего порядка.
Например:
1111 1111 1111 1111 1111 1111 1111 1000
>>>1
0111 1111 1111 1111 1111 1111 1111 1100
так...
mask = (~0 << 32-length >>> 32-length-start_pos)
И ваш окончательный ответ будет выглядеть примерно так:
(data & (~0 << 32-length >>> 32-length-start_pos)) >>> start_pos
Самая внешняя операция поворота перемещает замаскированные данные в биты младшего порядка.
Другие советы
Не уверен, почему вам нужно использовать short.Вот решение, использующее 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);
}