Arithmetic right shift and logical right shift of negative numbers in JavaScript are very confusing, especially logical right shift >>>. You will find that even a small negative number will get an extremely huge number after right shift. Why is this?
It turns out that in the logical right shift, the sign bit will move to the right along with the whole, which is equivalent to the movement of an unsigned number. The final result is a positive number because the sign bit does not exist. First, the logical right shift must produce a 32-bit number, and then the sign bit of the negative number is 1, which means that the positions from the 32nd bit to the sign bit are all filled with 1. Can such a number be small? For example, -1, logical The expression of right shifting by 0 bits is 1111 1111 1111 1111 1111 1111 1111 1111. Such numbers are treated as positive numbers! Therefore, if -1 is logically shifted to the right by N bits, the final result will be all 1!
The left shift operation preserves the sign bit of the number. For example, if you shift -2 to the left by 5 bits, you get -64 instead of 64. "Is the symbol still stored in bit 32?" Yes, but this happens behind the scenes in ECMAScript and developers don't have direct access to bit 32. Even if a negative number is output as a binary string, it is displayed with a negative sign (for example, -2 will display -10.)
Signed right shift operation
Yes The symbolic right shift operator is represented by two greater than signs (
var iOld = 64; //equal to binary 1000000
var iNew = iOld >> 5; //equal to binary 10 and decimal 2. Likewise, Moving the digits will create empty spaces. This time, the empty bit is to the left of the number, but after the sign bit. ECMAScript fills these empty bits with the value of the sign bit, creating a complete number, as shown below:
Unsigned right shift operator
The unsigned right shift operator is given by Three greater than signs (>>>) mean that it shifts all the digits of the unsigned 32-bit number to the right as a whole. For positive numbers, the result of the unsigned right shift operation is the same as the signed right shift operation.
Using the example in the signed right shift operation, shifting 64 right by 5 bits will become 2:
The unsigned right shift operation fills all empty bits with 0s. For positive numbers, this operates the same as the signed right shift operation, while negative numbers are treated as positive numbers.
Since the result of the unsigned right shift operation is a 32-bit positive number, the unsigned right shift operation of negative numbers always results in a very large number. For example, if you shift -64 right by 5 bits, you get 134217726. What if you get this result?
To achieve this, the number needs to be converted into its unsigned equivalent (although the number itself is still signed), which can be obtained with the following code:
var iUnsigned64 = -64 >>> 0;
Then, use toString() of Number type to get its real bit representation, using base 2: The code is as follows:
alert(iUnsigned64 .toString(2));
This will generate 11111111111111111111111111000000, which is the two's complement representation of the signed integer -64, but it is equal to the unsigned integer 4294967232.
For this reason, be careful when using the unsigned right shift operator.
Now let’s talk about the arithmetic right shift of negative numbers>>:
We found that -9>>2=-3, why is it -3?
First of all, the sign bit is unchanged and does not participate in the right shift. Then during the right shift of 9, if the lowest bit is 1, then the lowest bit will still be 1 after the right shift! This is very strange.