Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does 'x << ~y' represent in JavaScript?

People also ask

What does << mean in JS?

The left shift operator ( << ) shifts the first operand the specified number of bits, modulo 32, to the left. Excess bits shifted off to the left are discarded. Zero bits are shifted in from the right.

What is the difference between >> and >>> in JavaScript?

>> is arithmetic shift right, >>> is logical shift right. In an arithmetic shift, the sign bit is extended to preserve the signedness of the number.

What is the use of << and >> operator?

The bitwise shift operators are the right-shift operator ( >> ), which moves the bits of an integer or enumeration type expression to the right, and the left-shift operator ( << ), which moves the bits to the left.

What does >> mean code?

>> is the signed right shift operator. It shifts a bit pattern to the right. The bit pattern is given by the left-hand operand, and the number of positions to shift by the right-hand operand. When you shift right two bits, you drop the two least significant bits.


x << -n is equal to x << (32 - n)
~3 == -4 so
5 << ~3 === 5 << (32 - 4) === 5 << 28 which is 1,342,177,280

to be accurate X << -n is not the same as X << (32 - n) ... in fact it's both simpler and more complicated ... the valid range of a bit shift operator is 0 to 31 ... the RHS in a bit shift operator is first converted to an unsigned 32 bit integer, then masked with 31 (hex 1f) (binary 11111)

                   3 = 00000000000000000000000000000011  
                  ~3 = 11111111111111111111111111111100
       0x1f (the mask) 00000000000000000000000000011111
                       --------------------------------
            ~3 & 0x1f  00000000000000000000000000011100 = 28

when the magnitude is less than 32, it's exactly the same as what I posted above though

Bit operations work with 32 bit integers. Negative bit shifts are meaningless so are wrapped into positive 32 bit integers

How the << operator works

The rhs is converted to an unsigned 32bit integer - like explained here ToUInt32

ToUint32 basically takes a number and returns the number modulo 2^32


The ~ operator flips the bits of the item, while << is a bitwise left shift. Here is what is happening in binary step-by-step. Note that the most left bit being 1 signified a negative number, this format is twos compliment:

3         // (00000000000000000000000000000011 => +3 in decimal)
// ~ flips the bits
~3        // (11111111111111111111111111111100 => -4 in decimal)
// The number 5 (..00101) shifted by left by -4 (-4 unsigned -> 28)
5         // (00000000000000000000000000000101 => +5 in decimal)
5 << -4   // (01010000000000000000000000000000 => +1342177280 in decimal)

In the last line the bits are shifted and "rotated" to the other side, leading to a large positive number. In fact shifting by a negative number is similar to a bitwise rotation (overflowed bits are rotated to the other side), where shifting by positive numbers do not have such behaviour. The draw back is that the non-rotated bits are disregarded. Essentially meaning that 5 << -4 is the same as doing 5 << (32 - 4), that rather the rotation is actually a large shift.

The reasoning for this is because bit shifts are only a 5 bit unsigned integer. So the binary number in twos compliment-4 (11100) unsigned would be 28.


Your analysis is correct, except that you should not interpret ~3 (11100) (the bit-complement of 3 (00011)) as -4 , but as an unsigned (that is non-negative) 5-bit integer, namely 28 = 16 + 8 + 4 (11100).

This is explained in the ECMAScript standard (NB in most modern machines, positive and negative integers are represented in memory using two's complement representation):

12.8.3 The Left Shift Operator ( << )

NOTE Performs a bitwise left shift operation on the left operand by the amount specified by the right operand.

12.8.3.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression << AdditiveExpression

  1. Let lref be the result of evaluating ShiftExpression.
  2. Let lval be GetValue(lref).
  3. ReturnIfAbrupt(lval).
  4. Let rref be the result of evaluating AdditiveExpression.
  5. Let rval be GetValue(rref).
  6. ReturnIfAbrupt(rval).
  7. Let lnum be ToInt32(lval).
  8. ReturnIfAbrupt(lnum).
  9. Let rnum be ToUint32(rval).
  10. ReturnIfAbrupt(rnum).
  11. Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
  12. Return the result of left shifting lnum by shiftCount bits. The result is a signed 32-bit integer.

~x will reverse the bit representation of your x value (32 bits signed value with two's complement).

x << y is the left shift operator (here left). Your mathematical interpretation is correct :)

You can read more about bitwise operations over here: bitwise operators in Javascript