Main Tutorials

Java >> and >>> bitwise shift operators

In programming, bitwise shift operators, >> means arithmetic right shift, >>> means logical right shift, the differences:

  • >>, it preserves the sign (positive or negative numbers) after right shift by n bit, sign extension.
  • >>>, it ignores the sign after right shift by n bit, zero extension.

To work with bitwise shift operators >> and >>>. First, we need to know how Java uses two’s complement to represent signed numbers (positive and negative).

1. Java and Two’s complement.

Java uses two’s complement to represent signed numbers (positive and negative numbers). In the below example, we will show you how to express positive and negative numbers in two’s complement.

Note
In two’s complement, the first left bit (most significant bit) represents the sign, 0 is a positive number, 1 is a negative number

1.1 For example, 2 and -2

The binary format of 2 is 0000 0010


  0000 0010

The binary format of -2 (two’s complement) is 1111 1110


  0000 0010 (positive 2)
  1111 1101 (invert bits)
  1111 1110 (add 1)
  1111 1110 (-2 in binary)

1.2 Another example, 19 and -19

The binary format of 19 is 0001 0011


  0001 0011

The binary format of -19 is 1110 1101.


  0001 0011 (positive 19)
  1110 1100 (invert bits)
  1110 1101 (add 1)
  1110 1101 (-19 in binary)

2. Arithmetic Right Shift >> or Signed Extension.

The arithmetic right shift >> or signed right shift preserves the sign (positive or negative numbers) after bits shift. This >> operator fills all the left empty positions with the original most significant bit (the first bit on the left).

Arithmetic right shift

P.S Photo copied from Wikipedia.

2.1 For example, number 19 in 8 bits, and we arithmetic right shift by 2 bits 19 >> 2.


19         = |0001 0011|
                >> 2
19 >> 2    = |??00 0100|11

In the above example, the last 2 bits 11 are shifted out of the 8 bits, but what should we fill the left first two empty positions?

The answer depends on the original most significant bit (msb). In this example, the original msb is 0, and we fill in the ?? with 0.


19         = |{0=msb}001 0011|
                >> 2
19 >> 2    = |??00 0100|11
19 >> 2    = |0000 0100|11

2.2 Another example, number -19 in 8 bits, and we arithmetic right shift by 2 bits -19 >> 2.


-19        = |1110 1101|
                >> 2
-19 >> 2   = |??11 1011|01

In the above example, the original msb is 1, and we fill the ?? with 11.


-19        = |{1=msb}110 1101|
                >> 2
-19 >> 2   = |??11 1011|01
-19 >> 2   = |1111 1011|01

Again, in two’s complement, the first bit on the left (msb) represents the sign, 0 is a positive number, 1 is a negative number. The concept of copy the original most significant bit (msb) to fill in the empty bit will preserve the sign after bit shift – signed extension.

Question
Q : Wait, what is the answer to -19 >> 2?
A: The answer is 1111 1011 or -5.

This is how two’s complement works on negative number.


  1111 1011 (this is a negative number)
  1111 1010 (sub 1)
  0000 0101 (invert bits)
  0000 0101 (1x2^0 + 1x2^2 = 5)

In two’s complement, first bit on the left, 1 means negative, and the answer is -5.

3. Logical Right Shift >>> or Zero Extension.

This >>> logical right shift ignores the sign and fill all the left empty positions with zero.

Logical right shift

P.S Photo copied from Wikipedia.

3.1 For example, number 19 in 8 bits, and we logical right shift by 2 bits 19 >>> 2.


19         = |0001 0011|
                >>> 2
19 >>> 2   = |??00 0100|11

19         = |0001 0011|
                >>> 2
19 >>> 2   = |0000 0100|11

3.2 For negative number -19, it is the same. No matter what condition, the logical right shift will fill left empty positions with zero, ignore the sign.


-19        = |1110 1101|
                >>> 2
-19 >>> 2  = |??11 1011|01

-19        = |1110 1101|
                >>> 2
-19 >>> 2  = |0011 1011|01

Question
Q: Wait, again, what is the answer of -19 >>> 2?

For 8 bits. The answer is 59.


  0011 1011 (positive number)
  0011 1011 (1x2^0) + (1x2^1) + (1x2^3) + (1x2^4) + (1x2^5)
  0011 1011 (1 + 2 + 8 + 16 + 32) = 59

In Java, integer, 32 bits, 4 bytes. The answer is 1073741819.


  System.out.println(-19>>>2); // 1073741819

In Java, -19 , convert it to binary.


Input -19  = 11111111|11111111|11111111|11101101
-19 >> 2   = 11111111|11111111|11111111|11111011  = -5
-19 >>> 2  = 00111111|11111111|11111111|11111011  = 1073741819

Any use cases for these bitwise operator >>> or >>? Please comments, thanks.

Note
If you found any errors or typo, specially in the binary format, do comment and let me know 🙂

4. Java Print Integer in Binary format.

This is the Java program to use Integer.toBinaryString print an Integer in Binary format.

ByteSign.java

package com.mkyong.crypto.bytes;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ByteSign {

    public static final String OUTPUT_FORMAT = "%32s";

    public static void main(String[] args) {

        String STRING_FORMAT = "%-10s = %s";

        int number = 24;

        System.out.println("Positive Number");
        System.out.println(String.format(STRING_FORMAT, "Input " + number, printBinary(number)));
        System.out.println(String.format(STRING_FORMAT, number + " >> 2", printBinary(number >> 2)));      
        System.out.println(String.format(STRING_FORMAT, number + " >>> 2", printBinary(number >>> 2)));

        int number2 = -19;

        System.out.println("\nNegative Number");
        System.out.println(String.format(STRING_FORMAT, "Input " + number2, printBinary(number2)));
        System.out.println(String.format(STRING_FORMAT, number2 + " >> 2", printBinary(number2 >> 2)));
        System.out.println(String.format(STRING_FORMAT, number2 + " >>> 2", printBinary(number2 >>> 2)));

    }

    public static String printBinary(int number) {
        return printBinary(number, 8, "|");
    }

    public static String printBinary(int number, int blockSize, String separator) {

        // pad leading zero
        String pBinary = String
                .format(OUTPUT_FORMAT, Integer.toBinaryString(number))
                .replace(" ", "0");

        // split by blockSize
        List<String> result = new ArrayList<>();
        int index = 0;
        while (index < pBinary.length()) {
            result.add(pBinary.substring(index, Math.min(index + blockSize, pBinary.length())));
            index += blockSize;
        }

        return result.stream().collect(Collectors.joining(separator));
    }
}

Output

Terminal

Positive Number
Input 24   = 00000000|00000000|00000000|00011000
24 >> 2    = 00000000|00000000|00000000|00000110
24 >>> 2   = 00000000|00000000|00000000|00000110

Negative Number
Input -19  = 11111111|11111111|11111111|11101101
-19 >> 2   = 11111111|11111111|11111111|11111011
-19 >>> 2  = 00111111|11111111|11111111|11111011

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
3 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
salman
3 years ago

If an example were like this then what will be the internal process of this code?

int a=-5,b;
b=a<<5;
System.out.println(String.format("left shift"+b);

help, please…

salman
3 years ago
Reply to  salman

System.out.println(“left shift”+b);

sorry for this…

KISHORE
3 years ago

The best explanation ever. I saw multiple youtube videos and was not actually clear on the concept. This blog made it so clear. thanks a lot.