Operatory przesunięć a typ short, byte, char

0

Witam, napotkałem pewien problem przy operatorach przesunięć. Zgodnie z definicją << jest operatorem przesunięcia w lewo i wstawia, w binarnej wersji, zera na najmłodszych bitach. Operator >> jest operatorem przesunięcia w prawo i wstawia zera na najstarszych bitach jeśli wartość jest dodatnia oraz zera, gdy wartość jest ujemna. Operator >>> jest operatorem przesunięcia w prawo i niezależnie od znaku wartości wstawia zera na najstarszych bitach. Wszystko się zgadza poza jednym przypadkiem. Jeśli zmienna, którą przesuwamy jest typu short, byte lub char i jest ujemna to operator >>> nie wstawia zer na najstarszych bitach tylko jedynki, co zaprzecza definicji. Wiem też, że przed przesunięciem wartości tych typów następuje rzutowanie na int.

short s = -10; 
System.out.println(Integer.toBinaryString(s));
s >>>= 1;
System.out.println(Integer.toBinaryString(s));

Konsola:

11111111111111111111111111110110
11111111111111111111111111111011

a według definicji powinno być:
11111111111111111111111111110110
1111111111111111111111111111101
1

Problemem nie jest operator, ale konwersja. Operator >>> rozszerza lewy operand i zwracaną wartość do inta, która przy przypisaniu obcinana jest z powrotem o dwa bajty do shorta. Integer.toBinaryString przyjmuje inta, więc s musi znowu być rozszerzony do inta na podstawie bitu znaku:

short s = -10;  // 11111111 11110110

s >>>= 1;  // daje:
  int ext = s;  // 11111111 11111111 11111111 11110110
  int res = ext >>> 1;  // 01111111 11111111 11111111 11111011
  s = (short) res;  //  11111111 11111011

Integer.toBinaryString(s);  // 11111111 11111111 11111111 11111011

Swoją drogą, według definicji powinno być:
1111111 11111011
co można osiągnąć:

short s = -10;
int i = (s & 0xFFFF /* dwa młodsze bajty */) >>> 1;
Integer.toBinaryString(i);

1 użytkowników online, w tym zalogowanych: 0, gości: 1