Битовые операции. Неправильный сдвиг
Есть значение
byte b1 = (byte) 0xE2; //1110 0010
Из этого нужно получить значение 7 (десятичное) // 0111
Пробую сдвинуть на 5 разрядов вправо, получается 0xFF.
int result = b1 >> 5; // = 0xFF. А по идеи должно было получится 0000 0111 (значение 7 DEC)
Подскажите, что не так?
Правильный результат я получил с помощью BetSet.
BitSet result = getBitSet(new byte[] { b1 }, 0, 5, 3);
int dec = Arrays.copyOf(result.toByteArray(), 1)[0]; // = 7. b1 не всегда 0xE7, может быть и 0x2 и т.д. т.е. в этом случае в получаем просто 0
public static BitSet getBitSet(byte[] array, int fromByteIndex, int fromByteBitIndex, int bitsCount) {
BitSet arrayBitSet = BitSet.valueOf(array);
int fromIndex = fromByteIndex * 8 + fromByteBitIndex;
return arrayBitSet.get(fromIndex, fromIndex + bitsCount);
}
Ответы (2 шт):
Byte в яве сдвигать нельзя. Поэтому сначала он дополняется до int. В вашем случае единицами, т.к. первый бит в вашем байте - единица. Именно эти единицы и выходят потом в итоговом значении.
Полезная ссылка: How does bitshifting work in Java .
>> - оператор арифметического сдвига (SAR), он распространяет знаковый бит, который в данном случае единичный
Но в Java есть и оператор >>> (логический или беззнаковый сдвиг), который заполнит освободившееся место нулями
int b1 = 0xE2; //1110 0010
int result = b1 >>> 5;
System.out.print(result);
7
Поскольку при приведении байта к int происходит заполнение единицами, можно обнулить старшую часть промежуточного результата.
byte b1 = (byte) 0xE2; //1110 0010
int result = (b1 & 0xFF) >>> 5;
System.out.print(result);
В зависимости от задачи может оказаться проще наложить трёхбитовую маску 7 в конце.
int result = (b1 >>> 5) & 7;