Saturday, January 07, 2006

Java Operators

* << left-shift, >> right-shift, >>> unsigned right-shift
* only used on integer values
* binary numeric promotion is not performed on the operands; instead unary promotion is performed on each operand separately (JLS §15.19)
* both operands are individually promoted to int if their type is byte, short or char
* a long shift operator does not force a left-hand int value promotion to long (JLS§5.6.1)
* left-associative
* left-hand operator represents the number to be shifted
* right-hand operator specifies the shift distance

value << 2 // 2 is the distance to be shifted

* when the value to be shifted (left-operand) is an int, only the last 5 digits of the right-hand operand are used to perform the shift. The actual size of the shift is the value of the right-hand operand masked by 31 (0x1f). ie the shift distance is always between 0 and 31 (if shift value is > 32 shift is 32%value)

35 00000000 00000000 00000000 00100011
31 -> 0x1f 00000000 00000000 00000000 00011111
& -----------------------------------
Shift value 00000000 00000000 00000000 00000011 -> 3

-29 11111111 11111111 11111111 11100011
31 -> 0x1f 00000000 00000000 00000000 00011111
& -----------------------------------
Shift value 00000000 00000000 00000000 00000011 -> 3

* when the value to be shifted (left-operand) is a long, only the last 6 digits of the right-hand operand are used to perform the shift. The actual size of the shift is the value of the right-hand operand masked by 63 (0x3D) ie the shift distance is always between 0 and 63 (if shift value is greater than 64 shift is 64%value)
* the shift occurs at runtime on a bit-by-bit basis

Left-shift << (JLS §15.19)

* bits are shifted to the left based on the value of the right-operand
* new right hand bits are zero filled
* equivalent to left-operand times two to the power of the right-operand
For example, 16 << 5 = 16 * 25 = 512

Decimal 16 00000000000000000000000000010000

Left-shift 5 00000000000000000000000000010000
fill right 0000000000000000000000000001000000000
discard left 00000000000000000000001000000000

* the sign-bit is shifted to the left as well, so it can be dropped off or a different sign can replace it

Right-shift >> (JLS §15.19)

* bits are shifted to the right based on value of right-operand
* new left hand bits are filled with the value of the left-operand high-order bit therefore the sign of the left-hand operator is always retained
* for non-negative integers, a right-shift is equivalent to dividing the left-hand operator by two to the power of the right-hand operator
For example: 16 >> 2 = 16 / 22 = 4

Decimal 16 00000000000000000000000000010000

Right-shift 2 00000000000000000000000000010000
fill left 00000000000000000000000000000100
discard right 00000000000000000000000000000100 -> Decimal 4

Decimal -16 11111111111111111111111111110000

Right-shift 2 11111111111111111111111111110000
fill left 1111111111111111111111111111110000
discard right 11111111111111111111111111111100 -> Decimal -4

Unsigned right-shift >>> (JLS §15.19)

* identical to the right-shift operator only the left-bits are zero filled
* because the left-operand high-order bit is not retained, the sign value can change
* if the left-hand operand is positive, the result is the same as a right-shift
* if the left-hand operand is negative, the result is equivalent to the left-hand operand right-shifted by the number indicated by the right-hand operand plus two left-shifted by the inverted value of the right-hand operand
For example: -16 >>> 2 = (-16 >> 2 ) + ( 2 << ~2 ) = 1,073,741,820

Decimal 16 00000000000000000000000000010000

Right-shift 2 00000000000000000000000000010000
fill left 00000000000000000000000000000100
discard right 00000000000000000000000000000100 -> Decimal 4

Decimal -16 11111111111111111111111111110000

>>> 2 11111111111111111111111111110000
fill left 0011111111111111111111111111110000
discard right 00111111111111111111111111111100

No comments: