0

Why do both unsigned right shift (logical right shift) and signed right shift (arithmetic right shift) produce the same result for negative numbers?

Log.v("-59 >>> 5 expected 6, actual", String.valueOf((byte)(-59 >>> 5)));
Log.v("11000101 >>> 5 expected 00000110, actual",Integer.toBinaryString( -59 >>> 5));
Log.v("11000101 >> 5 expected 00000110, actual",Integer.toBinaryString( -59 >> 5));

Android Studio Logcat output

-59 >>> 5 expected 6, actual: -2

11000101 >>> 5 expected 00000110, actual: 111111111111111111111111110

11000101 >> 5 expected 00000110, actual: 11111111111111111111111111111110
user207421
  • 305,947
  • 44
  • 307
  • 483
It'sDK
  • 23
  • 7
  • 2
    "Is this a java VM bug" This should not be your first assumption. Please explain why you expected what you expected. – Andy Turner May 07 '19 at 09:02
  • https://stackoverflow.com/questions/3948220/behaviour-of-unsigned-right-shift-applied-to-byte-variable?rq=1 – Wrobel May 07 '19 at 09:07
  • 1
    "why it is same as signed right shift?" It's not. `111111111111111111111111110 != 11111111111111111111111111111110` (count the leading 1s). – Andy Turner May 07 '19 at 09:17
  • and int is 32 bit, not 8 like you seem to think... – Mark Rotteveel May 07 '19 at 10:00
  • binary representation of -59 is ‭11000101 when it is logically shifted right ‬the result should be 00000110 which is decimal 6. but when I am using >>> operator i get -2 equivalent to ‭11111110. this shows that a signed right shift is done and not a logical shift.‬ – It'sDK May 07 '19 at 10:41
  • thanks to @Wrobel , as u mentioned the solution works. thanks a lot once again. – It'sDK May 07 '19 at 10:59
  • can anyone explain me how b >>> 5; differs from (b & 0xff) >>> 5; this is the solution i got from the read i have mentioned. does it mean, if we do (b & 0xff) before shifting , it wont promote the number inside the paranthesis to integer??? – It'sDK May 07 '19 at 11:10
  • @It'sDK I updated my answer with your question about `0xff`. If it helped please upvote and accept it. – JensV May 07 '19 at 18:17
  • @JensV Thanks for your reply But I am still in need of a clear answer for the question follows. the Binary representation of -59 in eight bit binary (byte data type) is 1100 0101, which when processed by java vm will be promoted to integer data type , so a sign extension happens and we get 1111 1111 1111 1111 1111 1111 1100 0101. but why sign extension is not performed for 0xff. since java processes the number as integer then why it was not 1111 1111 1111 1111 1111 1111 1111 1111 ? – It'sDK May 10 '19 at 23:03

2 Answers2

1

This is normal behavior. Any integer with a negative value has a binary representation starting with infinite 1s.

So if you start out with say: -3 the binary representation looks like this:

...11 1101

So if we right shift this by 2 we get

...11 1111

Now for the unsgined/signed right shift. This relies on the fact that we don't have infinite digits in our integer. So say we have an 8bit integer assigned as -3 it looks like this:

1111 1101

If we do a signed shift, it will look at the MSB (most significant bit, the most left one) and preserve the value of that when shifting. So a signed shift right by 3 looks like this:

1111 1111

On the contrary, a unsigned right shift will not check the MSB and just shift right and fill with zeroes resulting in this:

0011 1111

This is exactly what you're seeing but the output truncates the preceding zeroes away.


If you don't know why negative integers are stored that way, check this answer.


As for why (b & 0xff) >>> 5 behaves differently

Integers in java are 32bit, that means the binary representation will have 32 digits. Your -59 will look like the following binary representation:

1111 1111 1111 1111 1111 1111 1100 0101 == -59
0000 0111 1111 1111 1111 1111 1111 1110 == -59 >>> 5

If you now and this together with 0xff you get the following:

1111 1111 1111 1111 1111 1111 1100 0101 == -59
0000 0000 0000 0000 0000 0000 1111 1111 == 0xff
0000 0000 0000 0000 0000 0000 1100 0101 == -59 & 0xff
0000 0000 0000 0000 0000 0000 0000 0110 == (-59 & 0xff) >>> 5
JensV
  • 3,997
  • 2
  • 19
  • 43
0

Right shift operator:- if the number is negative then it fills with 1. if the number is positive then it fills with 0. Unsigned Shift operator:- It fills with 0 irrespective of sign of the number.

peridin
  • 28
  • 3