Беззнаковый сдвиг вправо на подписанных байтах, приводящий к ошибкам

Я испытываю странную операцию сдвига вправо без знака, дающую неправильные результаты при попытке выполнить их на жестко закодированных, а не жестко закодированных данных на Java 8.

Я пытаюсь выполнить беззнаковый сдвиг вправо для подписанного байта 0xBF. Если я просто назначил байт со знаком переменной, а затем использовал переменную для выполнения беззнаковой операции сдвига вправо, я получил бы 0xDF. Если я жестко закодирую 0xBF в операцию сдвига вправо без знака, я получу 0x5F.

byte originalByte = (byte) 0xBF;
System.out.println("Original Data: " + toHexString(new byte[]{originalByte}));

byte rotatedByte = (byte) (originalByte >>> 1);
System.out.println("Rotated Data: " + toHexString(new byte[]{rotatedByte}));

byte signRemoved = (byte) (0xBF >>> 1);
System.out.println("Sign Removed Data: " + toHexString(new byte[]{signRemoved}));

Результат вышеупомянутого вызова Java.

Original Data: BF
Rotated Data: DF
Sign Removed Data: 5F

Как мне решить указанную выше проблему?


person thotheolh    schedule 13.08.2016    source источник
comment
сдвиг вправо без знака в Java - это немного неправильное название. Сдвинутое значение по-прежнему имеет знак, но бит знака сдвигается и заменяется нулем. Таким образом, имеет значение, если вы сдвинете byte на int, поскольку бит знака находится в другом месте.   -  person davmac    schedule 13.08.2016


Ответы (1)


В случае повернутого байта вы выполняете операцию с байтовым типом. В случае signRemoved вы выполняете операцию с типом int, а после завершения операции вы приводите его к байту. Поэтому результат другой.

int i = 0xBF; // this is int and the value is 191
byte b = (byte) 0xBF; // this is byte and value is -65 

int i2 = (i >>> 1) //here the operation is done on int result is 95
byte b2 = (byte) i2 // result stays 95

int i3 = b >>> 1 // here b is first promoted to int (-65) then  after right shift it becomes 2147483615
byte b3 = (byte) i3 // -33
person Viktor K.    schedule 13.08.2016
comment
Как мне получить 0xBF из байтового типа в 0x5F как байтовый без необходимости использовать целое число? - person thotheolh; 13.08.2016
comment
При использовании операторов сдвига байты всегда сначала преобразуются в целые числа, поскольку операторы сдвига работают с целыми числами в java. Это хорошо объясняет stackoverflow.com/questions/3948220/ - person Viktor K.; 13.08.2016