Reputation: 1988
Here's a tiny java program
public class otherclass {
public static void main(String[]args){
byte a=-5;
byte d= (byte) (a>>>1);
System.out.println(d);
byte e= (byte) (a>>>2);
System.out.println(e);
byte f= (byte) (a>>1);
System.out.println(f);
byte g= (byte) (a>>2);
System.out.println(g);
}
}
output:
-3
-2
-3
-2
The second two outputs (those -3 and -2 of the logical shifts) I understand.
negative 5 is 11111011
arithmetic shift shifts to the right and the extra added bit on the left is like the MSB. So one shift makes 11111101
which is negative 3. Negative two is also fine.
The logical shift is supposed to add zeros to the left. 11111011
should become 01111101
which is 125. How does it also output negative 3?
Upvotes: 0
Views: 105
Reputation: 178263
The missing piece of information is that Java promotes the values to int
when bit-shifting them, called binary numeric promotion. The byte
values are promoted to int
before they are shifted, then the shift occurs, then they are cast back to byte
.
-5 as byte : 11111011
-5 as int : 11111111 11111111 11111111 11111011
Bit shifted : 01111111 11111111 11111111 11111101
The zero is shifted in, but the cast back to byte
discards it all but the last 8 bits anyway.
Cast to byte: 11111101 (-3)
If you would like the >>>
operation to behave as if there were no binary numeric promotion, then you must mask out the final 8 bits from the promoted int
.
byte d= (byte) ((a & 0xFF)>>>1);
System.out.println(d);
byte e= (byte) ((a & 0xFF)>>>2);
System.out.println(e);
Output:
125
62
What's happening here:
-5 as byte : 11111011
-5 as int : 11111111 11111111 11111111 11111011
Bit masked : 00000000 00000000 00000000 11111011
Bit shifted : 00000000 00000000 00000000 01111101
The zero is shifted in as before, but the cast back to byte
discards it all but the last 8 bits anyway.
Cast to byte: 01111101 (125)
Note that this would occur with >>>
and with >>
, so only do the bit-and with 0xFF
on the >>>
operations.
Upvotes: 4