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

What does 'x << ~y' represent in JavaScript?
I understand that the bitwise SHIFT operation does this:
x << y AS x * 2y
And a tilde ~ operator does:
~x AS -(x+1)
So, I assume the following:
5 << ~3 AS 5 * 2-4 or 5 * Math.pow(2, -4)
It should result in 0.3125.
But, when I run 5 << ~3 it results in 1342177280.
What is a step-by-step explanation? How and why does this combination of operations result in 1342177280 instead of 0.3125?
(This question is similar to Stack Overflow question What are bitwise operators? about the bitwise SHIFT operator.)

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
Let lref be the result of evaluating ShiftExpression.
Let lval be GetValue(lref).
ReturnIfAbrupt(lval).
Let rref be the result of evaluating AdditiveExpression.
Let rval be GetValue(rref).
ReturnIfAbrupt(rval).
Let lnum be ToInt32(lval).
ReturnIfAbrupt(lnum).
Let rnum be ToUint32(rval).
ReturnIfAbrupt(rnum).
Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
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

5 << ~3 gives the same result as 5 << -4, you are right.
Important thing: shifting x << y really results into x * 2y, but it is not a direct usage, it is just a useful side-effect.
Moreover, if you have a negative y, it doesn't work in the same way.

Related

Confusion with left-shift operator

I am trying to create a 32-bit bitmask in JS. However, I don't understand what's happening here:
$ node
> const num = Math.pow(2, 31) - 1
undefined
> num
2147483647
# So far, so good
> num.toString(2)
'1111111111111111111111111111111'
> num.toString(2).length
31
# According to MDN, the left-shift operator does:
# "Excess bits shifted off to the left are discarded.
# Zero bits are shifted in from the right."
# But that's not what we see here. Instead, it seems to be wrapping.
> num << 1
-2
> (num << 1).toString(2)
'-10'
According to my understanding of the MDN docs, I'd expect to have a bitmask of 31 1s followed by 1 0. Instead, I get -10. What's going on here?
Javascript doesn't have Integer, but bitwise operators only make sense on Integer.
So before bitwise operators, javascript will apply ToInt32(val) to your num.
For "Signed 32 bits Integer", the top bit represents 'signed'.
Finally your num overflow the 'signed bit'.
My English is poor, you can check ECMAScript's Language Specification.
It is not wrapping. It is exactly working as the documentation you've linked. In your linked documentation, it says:
The operands of all bitwise operators are converted to signed 32-bit integers in two's complement format.
Your num is 2147483647, and this number in two's complement format is:
01111111 11111111 11111111 11111111
After left shifting num by 1, it becomes:
11111111 11111111 11111111 11111110
The above 32-bit two's complement value is -2 in decimal number. Hence, you get:
> num
2147483647
> num << 1
-2
If you call toString(2) with a negative decimal number -2, it follows some special rule of toString(). What it does is:
Take the magitude of the decimal. (-2 => 2)
Convert the decimal to base-2 string representation. (2 => '10')
Put the minus sign in front. ('10' => '-10')
Therefore, you get:
> (num << 1).toString(2)
> -10
You also get:
> (-2).toString(2)
> -10
Today I check your question again then know I misunderstand your main point yesterday.
This is your main point:
" I'd expect to have a bitmask of 31 1s followed by 1 0. Instead, I get -10."
Because Two's complement.
A negative number doesn't express value directly.
let num=Math.pow(2,31)-1
//num in memory=> 0111111111111111111111111111111
// ^
// |
// signed bit
//This number is positive, so
//nothing to do=> 0111111111111111111111111111111
num = num<<1
//num in memory=> 1111111111111111111111111111110
// ^
// |
// signed bit
//This number is negative, so flip then add 1
//flip => 1000000000000000000000000000001
//add 1 => 1000000000000000000000000000010 => '-10'

What exactly does shift operation whose right operand is over 31 do, in Javascript?

I know that operands of bitwise operation are treated as 32-bit integers in Javascript. So I thought that it would be zero'd out if I do << 32 on integer values. But it worked as if it's << 0. For what reason is it worked in that way? What exactly does shift operation whose right operand is over 31 do, in Javascript?
0b00000000000000000000000000000001 << 32 // 1
0b00000000000000000000000000000001 << 33 // 2
0b00000000000000000000000000000001 << 34 // 4
0b00000000000000000000000000000001 >> 30 // 0
0b00000000000000000000000000000001 >> 31 // 0
// Something weird is happening.......
0b00000000000000000000000000000001 >> 32 // 1
0b00000000000000000000000000000001 >> 33 // 0
It truncates the binary representation of the right operand.
From the documentation for Bitwise Shift Operators:
Shift operators convert their operands to 32-bit integers in
big-endian order and return a result of the same type as the left
operand. The right operand should be less than 32, but if not only the
low five bits will be used.
So in your example, 32 is 0b100000. Since it only takes the lowest five bits you're left with 0b00000, so it shifts the number by 0. Again, 33 is 0b100001 and the lowest five bits are 0b00001, so it shifts the number by 1. And so on.

Why do Ruby and JavaScript bitwise operators yield different results with the same operands?

Why do Ruby and JavaScript bitwise operators yield different results with the same operands?
For example:
256 >> -4 # => 4096 (Ruby)
256 >> -4 # => 0 (Javascript)
Any tips/pointers are appreciated.
For the Ruby version, it looks like 256 >> -4 is equivalent to 256 << 4, so the negative operand essentially just switches the direction of the shift.
From looking at the ECMAScript specification for the right-shift operator, in JavaScript, the operand is converted to an unsigned 32-bit integer before the shift, so the -4 becomes 4294967292. After this conversion the 5 least-significant bits are used for the shift, in other words we would end up shifting by 4294967292 & 0x1f bits (which comes out to 28). It probably shouldn't surprise you at all to see that 256 >> 28 gives 0.
For convenience, here is the text from the spec (steps 6 and 7 are most relevant to your confusion here):
The Signed Right Shift Operator ( >> )
Performs a sign-filling bitwise right shift operation on the left operand by the amount specified by the right operand.
The production ShiftExpression : ShiftExpression >> AdditiveExpression is evaluated as follows:
Let lref be the result of evaluating ShiftExpression.
Let lval be GetValue(lref).
Let rref be the result of evaluating AdditiveExpression.
Let rval be GetValue(rref).
Let lnum be ToInt32(lval).
Let rnum be ToUint32(rval).
Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
Return the result of performing a sign-extending right shift of lnum by shiftCount bits. The most significant bit is propagated. The result is a signed 32-bit integer.
As a side note, if you want to play around with this by converting a value to an unsigned 32-bit integer you can use val >>> 0 as seen in touint32.js from V8 JavaScript Engine.

Left shifting with a negative shift count in Javascript

A thing which I noticed in Javascript -
a << -1
Returns 0 when a = even.
Returns -2147483648 when a = odd.
Similarly, different values are returned when -1 is changed to some other -ve number.
Can someone explain what bit operations are taking place under the hood ? Or is the behavior undefined ?
Thanks
EDIT
Also shouldn't Zero-fill right shift i.e. -2 >>> 1 return 7 ?
-2 = 1110. After, right shift with zero-fill, it should give 0111 = 7
but
a = -2; console.log(a >>> 1);
returns
2147483647
I too wondered about this which is how I landed here. I’ve done a little research and figured out the behavior. Essentially JavaScript treats the operand and shift value as sequences of bits rather than as numbers. It works with 32 bit integers (floats get truncated) and the maximum shift is 32 bits. If we shift by a number greater than 32, all the bits would shift out, resulting in zero. To ensure the shift is less than or equal to 32, JavaScript truncates the 5 least significant bits [a << (b&0x1F)] or possibly with the modulus method [a << (b%32)] which yields the same result.
With that out of the way, think of the negative number you are shifting by as a sequence of bits, not a negative number (i.e. -1). In this case b = -1 = 0xFFFFFFFF. Since this number is larger than 32, it is truncated 0xFFFFFFFF & 0x1F = 31 or 0xFFFFFFFF % 32 = 31.
So in your example “a" gets shifted all the way from the least significant bit to the most significant bit (the sign bit). Therefor the result of the shift is either 0x00000000 or (0x80000000 = -2147483648) depending on whether the operand had the 1 bit set (odd or even).
Got the answer to the second part of my question i.e. -2 >>> 1 = 7.
Javascript always deals with 32 bits. So when I do -2 >>> 1, what really happens under the hood is -
11111111111111111111111111111110 >>> 1 which gives 01111111111111111111111111111111 = (2147483647)base10
The LeftShift operator adds zeros to the right of the binary representation of a number, shifting the bits to the left. Only the 5 least significant digits of the additive expression are used. So:
var x = 5 // 101
alert( x << 1 ); // 1010 = 10
alert( x << 2 ); // 10100 = 20
alert( x << 3 ); // 101000 = 40
alert( x << 4 ); // 1010000 = 80
alert( x << 64 ); // 101 = 5
The last expression returns 5 as shift only uses the last 5 bits of the the additive expression, which is 1000000 so only the 00000 part is used.

Bitwise operator x >> 1 and x >> 0 [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
What do these operators do?
>> in javascript
Can somebody please explain the bitwise operator >> 1?
example:
65 >> 1 = 32
and also when >> 0
what does it achieve in this example:
var size = (Math.random() * 100 >> 0) + 20;
var size = (Math.random() * 100 >> 0) + 20;
>> 0 in the above example is used to eliminate the fractional portion, as follows:
Math.random() returns a number between 0 and 0.99999999...
This number multiplied by 100 gives you another number between 0 and 99.999999...
This number is right shifted 0 times. The number is implicitly cast to an integer for the shift operation; right shifting 0 times does not have any effect on the value of the resulting integer. You thus end up with an integer between 0 and 99. Note that you could have used the Math.floor() function instead of >> 0.
Add 20 to the integer, the result is an integer between 20 and 119.
Bitwise operator >> means shift right.
It moves the binary value to the right (and removes the right-most bit).
65 >> 1 in binary is:
1000001 >> 1 = 100000 = 32
It effectively divides the number into 2 and drops the remainder.
The operator '>>' shifts the contents of a variable right by 1 bit. This results, effectively, in integer division of that value by 2 as you show in your example:
65 >> 1 = 32
Let's say that a variable is always 32 bits long. The example then says:
65 decimal >> 1 = 32 or, in hex, 0x000041 >> 1 = 0x00000020
More generally: the operator '>>' divides its operand, as a 32-bit integer, by the power of 2 whose value is the shift length. Thus:
129 decimal >> 1 = 64 or 0x000081 >> 1 = 0x000040
129 decimal >> 2 = 32 or 0x000081 >> 2 = 0x000020
129 decimal >> 5 = 2 or 0x000081 >> 5 = 0x000002
and
129 decimal >> 8 = 0 or: 0x000081 >> 8 = 0x000000
The operator '<<' multiplies its operand, as you'd expect.
I don't know how Math.random( ) operates, but I'm willing to bet that the shift of its floating-point returned value right by 0 turns that number into an integer, because shifting left and right has arithmetic meaning only when the operand is an integer.
The bitwise shift operator shifts each bit of the input x bits to the right (>>) or to the left (<<).
65 is 1000001, thus 65 >> 1 = 0100000, which is 32.
EDIT
Here are some useful links:
http://en.wikipedia.org/wiki/Bitwise_operation
http://javascript.about.com/library/blbitop.htm
http://www.java2s.com/Tutorial/JavaScript/0040__Operators/ShiftLeft.htm
>> X takes the binary number and moves all the digits right by X places.
In your example, you use 65, which is 01000001 in binary. If you shift that right by one, the first space (on the left) gets filled in with a 0, and the last digit 'falls off the end'. Giving 00100000, which is the binary representation for 32.
>> 0, therefore shifts the number 0 spaces to the right, and does nothing.
'<< X', does the same, but shifts the number to the left.
These can be compared to multiplying by 2^X (Left-shift) or divinding by 2^X (right-shift), but it should be noted that a binary shift is much faster than a division operation.
You can understand why the output is 32 from rsplak's post. >> is the Right Bit Shift operator and using it as >> 1 will cause every bit to be shifted one place to the right. This means, if the rightmost bit was 1, it would get expelled and the left most bit will contain 0.
The bitwise operator shifts an expression by a number of digits. So in your example you have
65 which ist binary 0100 0001 shiftet 1 position to the right so you got 0010 0000 which is 32 decimal.
Another example:
48 >> 3 = 6
48 decimal is 0011 0000 binary shifted 3 to the right is 0000 0110 which is 6 decimal.
For your second example I can not help you - I can not image why I would shift an expression by 0 positions but maybe you can find out debugging it?

Categories

Resources