0

I am having a difficult time wrapping my head around negative unsigned bitwise operators. For example, I have the code below. It prints out the value 7 and I don't understand why.

int num1 = -37, num2 = -3;    
System.out.println( num1 >>> num2);
// Essentially the same as System.out.println( -37 >>> -3); 
// I just wanted to emphasize that i am working with Integers

From my knowledge, the number -37 in binary format is as shown below.

11111111 11111111 11111111 11011010 = -37 (in decimal format)

If we are unsigned right shift of 3 ( -37 >>> 3, not -37 >>> -3), from my knowledge (please correct me if my theory is flawed or lacking key concepts), it shifts the bytes to the right by 3 and the 3 bits that fall out on the right most position appear on the left most position in a flipped down state (from zero to one), meaning that we get the following result.

00011111 11111111 11111111 11111011 = 536870907 (in decimal format).

However, if we apply an unsigned right shift of -3 ( -37 >>> -3), we get the result 7. I don't understand why it is returning 7. Could somebody please explain it to me?

J. Lee
  • 513
  • 4
  • 15

1 Answers1

1

It seems counter-intuitive, but when shifting an int, only the last 5 bits of the shift amount are used, according to the JLS, Section 15.19.

If the promoted type of the left-hand operand is int, then only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.

This means that -3 only has the last 5 bits used, or 29. Here's -3 in bits to show what's going on:

11111111 11111111 11111111 11111101

The last 5 bits are 11101, or 29 in decimal.

The right-shift distance is 29, which means that the first 3 bits are kept and shifted all the way to the right. Taking -37:

11111111 11111111 11111111 11011010

After the unsigned shift of 29 places, 7 is left:

00000000 00000000 00000000 00000111

As you can see, a negative shift amount is confusing at best. Try to avoid it and always attempt to use an actual number between 0 and 31 for the shift amount for shifting ints.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • Thank you for the explanation and also for the tips on when not to use them. I was just playing around with the bitwise operators and trying to grasp a greater understanding of how they work. I am guessing that negative unsigned right shift (that sounds weird) would simply make the code more difficult to understand, and it does make sense from your explanation. – J. Lee Jul 09 '15 at 00:47