Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What good does zero-fill bit-shifting by 0 do? (a >>> 0) [duplicate]

I was looking at code from Mozilla that add a filter method to Array and it had a line of code that confused me.

var len = this.length >>> 0; 

I have never seen >>> used in JavaScript before.
What is it and what does it do?

like image 775
Kenneth J Avatar asked Nov 30 '09 20:11

Kenneth J


People also ask

What does bit shifting by 0 do?

1 in binary is 0001 , then bitshifting it by 0 won't do anything, which aligns with what you observed. So any number x << 0 is equivalent to x * 2^0 , which is x * 1 , which is just x .

What does 1 << 0 do in C?

1 << 0 is 1 shifted to the left by 0 positions, which is just 1.

Which instruction shift the 0 in most significant bit?

Logical shift However, as the logical right-shift inserts value 0 bits into the most significant bit, instead of copying the sign bit, it is ideal for unsigned binary numbers, while the arithmetic right-shift is ideal for signed two's complement binary numbers.

What is the operator for shift right with zero fill?

The unsigned right shift operator ( >>> ) (zero-fill right shift) evaluates the left-hand operand as an unsigned number, and shifts the binary representation of that number by the number of bits, modulo 32, specified by the right-hand operand.


2 Answers

It doesn't just convert non-Numbers to Number, it converts them to Numbers that can be expressed as 32-bit unsigned ints.

Although JavaScript's Numbers are double-precision floats(*), the bitwise operators (<<, >>, &, | and ~) are defined in terms of operations on 32-bit integers. Doing a bitwise operation converts the number to a 32-bit signed int, losing any fractions and higher-place bits than 32, before doing the calculation and then converting back to Number.

So doing a bitwise operation with no actual effect, like a rightward-shift of 0 bits >>0, is a quick way to round a number and ensure it is in the 32-bit int range. Additionally, the triple >>> operator, after doing its unsigned operation, converts the results of its calculation to Number as an unsigned integer rather than the signed integer the others do, so it can be used to convert negatives to the 32-bit-two's-complement version as a large Number. Using >>>0 ensures you've got an integer between 0 and 0xFFFFFFFF.

In this case this is useful because ECMAScript defines Array indexes in terms of 32 bit unsigned ints. So if you're trying to implement array.filter in a way that exactly duplicates what the ECMAScript Fifth Edition standard says, you would cast the number to 32-bit unsigned int like this.

(In reality there's little practical need for this as hopefully people aren't going to be setting array.length to 0.5, -1, 1e21 or 'LEMONS'. But this is JavaScript authors we're talking about, so you never know...)

Summary:

1>>>0            === 1 -1>>>0           === 0xFFFFFFFF          -1>>0    === -1 1.7>>>0          === 1 0x100000002>>>0  === 2 1e21>>>0         === 0xDEA00000          1e21>>0  === -0x21600000 Infinity>>>0     === 0 NaN>>>0          === 0 null>>>0         === 0 '1'>>>0          === 1 'x'>>>0          === 0 Object>>>0       === 0 

(*: well, they're defined as behaving like floats. It wouldn't surprise me if some JavaScript engine actually used ints when it could, for performance reasons. But that would be an implementation detail you wouldn't get to take any advantage of.)

like image 180
bobince Avatar answered Oct 05 '22 11:10

bobince


The unsigned right shift operator is used in the all the array extra's method implementations of Mozilla, to ensure that the length property is a unsigned 32-bit integer.

The length property of array objects is described in the specification as:

Every Array object has a length property whose value is always a nonnegative integer less than 232.

This operator is the shortest way to achieve it, internally array methods use the ToUint32 operation, but that method is not accessible and exist on the specification for implementation purposes.

The Mozilla array extras implementations try to be ECMAScript 5 compliant, look at the description of the Array.prototype.indexOf method (§ 15.4.4.14):

 1. Let O be the result of calling ToObject passing the this value     as the argument. 2. Let lenValue be the result of calling the [[Get]] internal method of O with     the argument "length". 3. Let len be ToUint32(lenValue). .... 

As you can see, they just want to reproduce the behavior of the ToUint32 method to comply with the ES5 spec on an ES3 implementation, and as I said before, the unsigned right shift operator is the easiest way.

like image 32
Christian C. Salvadó Avatar answered Oct 05 '22 10:10

Christian C. Salvadó