Есть несколько вещей, которые нужно помнить о типах данных 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
Операция внешнего поворота перемещает ваши замаскированные данные в младшие биты.