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