Witscale Test Center

9.4 Binary operators > 9.4.5 The shift operators


9.4.5 The shift operators

In arithmetic operation, you manipulate the values of operands. Java allows you to manipulate the bit representations of these values as well. You can shift the bits to the right-hand side or to the left-hand side. Figure 9.1 shows simple shifting of bits to right by 1 bit and to the left by 3 bits.

 

 

 

 


 

 

Figure 9.1 Shifting of bits in a 32-bit bit representation

 

Figure shows that when you right shift by 1 bit, all the bits move to the right by one bit. An empty space is created shown with a question mark. Since the bit presentation is only 32 bits, the right-most bit is fell over and is lost . Similarly, when you left shift by 3 bits, every bit is shifted to left by 3 places and three empty spaces are created. The leftmost three bits in original  bit representation are lost. Thus, the bits are pushed out on the left and the right side of the bit representation during the shifting.

Java provides you with three shift operators. You can apply them to the operands of integral types only. The << and >> does signed left and right shift respectively. The >>> does unsigned right shift. The basic shifting is common in all three types as shown in figure 9.1. The fact that differentiates them is what bits are pushed in to replace the empty places.

Signed left shift << operator

In case of signed left shift, 0s are shifted in to take the empty places. The shift is binary operand, the first operand is the number for which you want to do the shift operation and the second operand is the number of bits with which you want to shift it. For example, you can do a signed left shift of -8 by 4 bits as:

  

   int  a = -8 << 2;

 

The bit representation of -8 is shifted to the left by 2 bits. This will create 2 empty places on the LSB (least-significant-bit or right-most) side. They are filled in with 0s. Figure 9.2 shows the signed left shift of -8 by 2 bits.

 


Figure 9.2 Signed left shift where 0’s are pumped in from right

 

The two empty spaces created are filled in with two 0s which are pumped in from the right side. The signed shift operations have an interesting effect on the value of first operand. When you left shift the number by n bits you effectively get its value multiplied by 2n. Therefore -8 << 2 will give you -32.

Signed right shift >> operator

The signed right shift operator is the only shift operator where the sign of a number is taken into account while bit shifting. The right shift creates empty spaces on the leftmost side. These empty places created on the MSB (most-significant-bit or leftmost) side of bit representation are filled with 0s if the MSB of original number is 0 (i.e is the number is positive) or it is filled with 1s if the MSB is 1 (i.e. the number is negative). For example,  the signed right shift on -8 is performed as:

 

 int a = -8 >> 2;

 


 Since -8 is a negative number, its MSB in its bit representation is 1. When it is shifted to the right by two bits, two empty spaces are created. They are filled in with 1s because the sign bit is 1. Figure 9.3 shows the signed right shift. The two 1s are pumped in from the left side to fill in the empty spaces.

 

 

Figure 9.3 Signed right shift where the sign bit is pumped in from left

 

The sign bits are pushed in during the signed right shift because this operation needs to maintain the sign of its operand. In simple word, a signed right shift of a negative number always results into a negative number. For positive numbers, the sign bit is 0. In that case 0s are pumped in during the signed right shift. When you perform a signed right shift on a number by n bits, you effectively divide its value by 2n. Therefore -8 >> 2 will give you -2.

 

The signed right shift operations wraps if all the bits become 1. The bit representation with all 1s represent a value -1.  If you perform a signed right shift of -1 (-1 >> n) by any number of bits, the result is always -1.

 

Unsigned right shift >>> operator

As the name suggest, the unsigned right shift does not take the sign of its operand into consideration. When the number is right shifted, always 0s are pumped in. As you can imagine, if the number is negative and if you do unsigned right shift even by 1 bit, you will effectively change the sign of that number. The MSB of negative number must be 1, but unsigned right shift even by 1 bit will make it 0 making the number a positive one. For example, the following code performs unsigned right shift of -8, the result is a positive number:

 

int a = -8 >>> 2;

 

The bit representation of -8 is shifted to right by 2 bits. This will create two empty places on the MSB (left-most) side which are then filled in with 0. Figure 9.4 shows the unsigned right shift. The two 0s pumped in from the left side to fill in the empty spaces.

 

 

 

 


 

 

Figure 9.4 Unsigned right shift where 0’s are pumped in from left regardless of the sign bit

 

Unlike the signed operators, the unsigned right shift does not actually divide by 2 or powers of 2. It cannot do the division, as it does not keep the sign. The result of unsigned shift is always a positive number.

 

Java does not have any operator for unsigned left shift such as <<< as it does not make any sense to have one. If Java had such operator, it would have performed same as the signed left shift. Be careful with a question code having this hypothetical operator.

 

The shift operators are applied only to the integral types. In fact, they are really applied only to the operands of type int and long. If you apply it to a byte, char or short value, it is first promoted to an int value and then the shift operators are applied. This is due to the "arithmetic promotion of operands" which will be discussed in details in the next chapter. For now remember that numeric operands are converted to at least (equivalent) int value before any binary operator is applied.

Wrapping of second operand in shift operations

The second operand in the shift operators represents the number of bits by which (the bit representation of a) value is shifted. For shifting to be of any sense, this second operand should be smaller than the total number of bits in the bit representation of the first operand. For instance, any int value has 32 bits in its representation. Therefore, it should be shifted by maximum 31 bits. If shifting is done longer than that it would be meaningless as it will always have either all 1's or all 0's. The fun part of all this is that you need not worry about what is the maximum value of this second operand while applying the shift operators. For instance, the following code is valid.

 

int a = 8;

int b = a << 65;

 

Now Java does not actually left shift the value by 65 bits (if it does, the result would be 0). Instead, it automatically wraps the second operand 65 by implicitly finding out the modulo 32 of it.  The value (65% 32) is 1. Therefore, in reality, the number a is left-shifted only by 1 bit.

All of the following statements will produce exactly the same value because of the wrapping of second operand.

  

int a = 8;

int b1 = a << 1;

int b2 = a << 33; // The second operand is wrapped to 33%32 ==> 1

int b3 = a << 65; // 65%32 ==> 1

int b4 = a << 97; // 97%32 ==> 1

 

The second operand is wrapped to modulo 32 value. Since 33%32 is same as 65%32, they both left shift the number by 1 bit. If the number you are shifting is of long type, then the second operand is wrapped to a modulo 64 value.