2

I know what diffirences between >> and >>>. but I did not get the output that i expected.

example.

byte foo;

// this part printing -61 so no problem with this part
foo = -121; // -121 = 10000111
// foo >> 1 = 11000011 = -61
System.out.println( (byte) (foo >> 1) );  


foo = -121; // -121 = 10000111
// foo >>> 1 = 01000011 = 67
System.out.println( (byte) (foo >>> 1) );
// problem: why is this part printing -61 instead of 67 ?

thanks.

Nomad
  • 918
  • 6
  • 23
  • https://stackoverflow.com/questions/2811319/difference-between-and – Dakoda Aug 29 '17 at 16:47
  • 1
    Bitwise operators...from the documentation `The signed left shift operator "<<" shifts a bit pattern to the left, and the signed right shift operator ">>" shifts a bit pattern to the right. The bit pattern is given by the left-hand operand, and the number of positions to shift by the right-hand operand. The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension`...link https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html – Hackerman Aug 29 '17 at 16:47
  • 2
    Hackman and Progman obviously didn't bother to read the question! – Nir Alfasi Aug 29 '17 at 16:50
  • This is not a dup... @davidxxx – Nir Alfasi Aug 29 '17 at 16:59

2 Answers2

7

>>> operates on int values, so it widens its arguments to int first. So it gets sign-extended to

 11111111111111111111111110000111

which logical right shifts to

 01111111111111111111111111000011

which, when you take the last 8 bits as a cast to byte does, gives

 11000011

which is -61.

If you don't want that implicit sign extension before the shift, you'll have to write

(byte) ((foo & 0xFF) >>> 1)
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • Thanks for the answer! I was starting to investigate when I saw that `foo` gets treated like an `int` and then saw your answer. Totally makes sense! – Nir Alfasi Aug 29 '17 at 16:57
  • do you know why java convert byte variables to int automaticilly ? this doesn't make sense ? – Nomad Aug 31 '17 at 10:52
1

Some background information in addition Louis Wasserman's excellent answer:

This is specified in jls-15.19 Shift Operators:

Unary numeric promotion (§5.6.1) is performed on each operand separately. (Binary numeric promotion (§5.6.2) is not performed on the operands.)

And the jls-5.6.1 Unary Numeric Promotion:

  • If the operand is of compile-time type Byte, Short, Character, or Integer, it is subjected to unboxing conversion (§5.1.8). The result is then promoted to a value of type int by a widening primitive conversion (§5.1.2) or an identity conversion (§5.1.1).

  • Otherwise, if the operand is of compile-time type Long, Float, or Double, it is subjected to unboxing conversion (§5.1.8).

  • Otherwise, if the operand is of compile-time type byte, short, or char, it is promoted to a value of type int by a widening primitive conversion (§5.1.2).

  • Otherwise, a unary numeric operand remains as is and is not converted.

(emphasis mine)

And 5.1.2. Widening Primitive Conversion:

A widening conversion of a signed integer value to an integral type T simply sign-extends the two's-complement representation of the integer value to fill the wider format.

Community
  • 1
  • 1
Hulk
  • 6,399
  • 1
  • 30
  • 52