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.
  • 右移n位后,它会保留符号(正数或负数)
  • >>>, it ignores the sign after right shift by n bit, zero extension.
  • 右移n位,它将忽略符号

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).

要使用按位运算符>>和>>>。首先,需要了解Java如何使用补码来表示带符号的数字(正数或负数)

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.

Java使用两个补码来表示带符号的数字(正数和负数)。在下面的示例中,将向展示如何用两个补码表示正数和负数

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

在二进制补码中,左第一位(最高有效位)代表符号,0为正数,1为负数

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).

算术右移>>或带符号的右移会保留位移位后的符号(正数或负数)该>>运算符使用原始的最高有效位(左侧的第一位)填充所有左侧的空白位置

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?

在上面的示例中,最后2位11从8位中移出了,但是我们应该在左边的前两个空白位置填充什么呢?

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.

答案取决于原始的最高有效位(msb)在此示例中,原始msb为0,我们填写??为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.

再举一个例子,在8位数字中为-19,然后算术右移2位-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.

在上面的示例中,原始msb为1,我们填充了??为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.

同样,以二进制补码形式,左边的第一位(msb)表示符号,0是正数,1是负数。复制原始最高有效位(msb)来填充空位的概念将在移位后保留符号

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.

在二进制补码中,左边的第一位是1,表示负数,答案是-5

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

逻辑右移>>>或零扩展

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

此>>>逻辑右移忽略该符号,并用零填充所有左边的空白位置

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,它是相同的。无论什么条件,逻辑右移都将用零填充左空白位置,而且会忽略符号

-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.

在Java中,整数是32位4字节。答案是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.

这是Java程序使用Integer.toBinaryString以Binary格式打印Integer

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

posted @ 2020-06-30 15:28  PrimerPlus  阅读(2900)  评论(0编辑  收藏  举报