What does the >> symbol mean? On this page, there's a line that looks like this:
var i = 0, l = this.length >> 0, curr;
It's bitwise shifting.
Let's take the number 7, which in binary is 0b00000111
7 << 1 shifts it one bit to the left, giving you 0b00001110, which is 14
Similarly, you can shift to the right: 7 >> 1 will cut off the last bit, giving you 0b00000011 which is 3.
[Edit]
In JavaScript, numbers are stored as floats. However, when shifting you need integer values, so using bit shifting on JavaScript values will convert it from float to integer.
In JavaScript, shifting by 0 bits will round the number down* (integer rounding) (Better phrased: it will convert the value to integer)
> a = 7.5;
7.5
> a >> 0
7
*: Unless the number is negative.
Sidenote: since JavaScript's integers are 32-bit, avoid using bitwise shifts unless you're absolutely sure that you're not going to use large numbers.
[Edit 2]
this.length >> 0 will also make a copy of the number, instead of taking a reference to it. Although I have no idea why anyone would want that.
Just like in many other languages >> operator (among << and >>>) is a bitwise shift.
Related
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?
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'.
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.)
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.
That is the unsigned right bit shift operator. The difference between this and the signed right bit shift operator, is that the unsigned right bit shift operator (>>>) fills with zeroes from the left, and the signed right bit shift operator (>>) fills with the sign bit, thus preserving the sign of the numerical value when shifted.
Driis has sufficiently explained what the operator is and what it does. Here's the meaning behind it/why it was used:
Shifting any direction by 0 does returns the original number and will cast null to 0. It seems that the example code that you are looking at is using this.length >>> 0 to ensure that len is numeric even if this.length is not defined.
For many people, bitwise operations are unclear (and Douglas Crockford/jslint suggests against using such things). It doesn't mean that its wrong to do, but more favorable and familiar methods exist to make code more readable. A more clear way to ensure that len is 0 is either of the following two methods.
// Cast this.length to a number
var len = +this.length;
or
// Cast this.length to a number, or use 0 if this.length is
// NaN/undefined (evaluates to false)
var len = +this.length || 0;
>>> is the unsigned right shift operator (see p. 76 of the JavaScript 1.5 specification), as opposed to the >>, the signed right shift operator.
>>> changes the results of shifting negative numbers because it does not preserve the sign bit when shifting. The consequences of this is can be understood by example, from an interpretter:
$ 1 >> 0
1
$ 0 >> 0
0
$ -1 >> 0
-1
$ 1 >>> 0
1
$ 0 >>> 0
0
$ -1 >>> 0
4294967295
$(-1 >>> 0).toString(16)
"ffffffff"
$ "cabbage" >>> 0
0
So what is probably intended to be done here is to get the length, or 0 if the length is undefined or not an integer, as per the "cabbage" example above. I think in this case it is safe to assume that this.length will never be < 0. Nevertheless, I would argue that this example is a nasty hack, for two reasons:
The behavior of <<< when using negative numbers, a side-effect probably not intended (or likely to occur) in the example above.
The intention of the code is not obvious, as the existence of this question verifies.
Best practice is probably to use something more readable unless performance is absolutely critical:
isNaN(parseInt(foo)) ? 0 : parseInt(foo)
Two reasons:
The result of >>> is an "integral"
undefined >>> 0 = 0 (since JS will try and coerce the LFS to numeric context, this will work for "foo" >>> 0, etc. as well)
Remember that numbers in JS have an internal-representation of double.
It's just a "quick" way of basic input sanity for length.
However, -1 >>> 0 (oops, likely not a desired length!)
Sample Java Code below explains well:
int x = 64;
System.out.println("x >>> 3 = " + (x >>> 3));
System.out.println("x >> 3 = " + (x >> 3));
System.out.println(Integer.toBinaryString(x >>> 3));
System.out.println(Integer.toBinaryString(x >> 3));
Output is the following:
x >>> 3 = 536870904
x >> 3 = -8
11111111111111111111111111000
11111111111111111111111111111000
In JavaScript code where the 8 bits of a byte represent 8 Boolean "decisions" (aka: flags), there is a need to isolate each given bit for conversion to a Boolean variable. Consider my solution using String parsing:
var bitParser = function (_nTestByte, _nBitOrdinal) {
var bits = ("00000000" + _nTestByte.toString(2)).slice(-8); // convert to binary and zero-pad
return bits[_nBitOrdinal] === "1";
};
console.log(bitParser(0b10100101, 2)); // ECMAScript 6+ prefix, returns true
It works, and shows the desired result. However I have a hypothesis stating that a bit shifting technique would be a faster option than String manipulation. I tend to believe that but desire to prove it.
The problem is, I have yet to produce such a function that works correctly, let alone something I can test. I have created the following logic plan that I believe is accurate:
/*
LOGIC PLAN
----------
0) Remember: all bitwise operators return 32 bits even though we are using 8
1) Left shift until the desired bit is the left-most (highest) position;
2) Right shift (zero filling) 31 bits to eliminate all right bits
*/
The implementation of the login plan follows. Because of the 32 bit nature of bitwise operators, its my belief that the entire left 3 bytes (24 bits) must be shifted off first before we even reach the byte being worked on. Then, assuming a scenario where the 3rd bit from the left (String ordinal 2) is the desired bit, I am shifting off 2 more bits (ordinals 0 & 1), for a total of 26 bits of left shifting.
This should produce a binary number with the desired bit all the way left followed by 31 undesired zero bytes. Right shifting those 31 bits away produces a binary with 31 (now) leading zero bits which evaluates to whatever the value of the desired bit is. But of course, I would not be writing this question if THAT were true, now would I? :-)
// hardcoded, assuming the second "1" (ordinal 2) is the bit to be examined
console.log((0b10100101 << 26) >> 31); // instead of 1, returns -1
I feel like I am really close, but missing something or pushing JavaScript too hard (lol).
In JavaScript code where the 8 bits of a byte represent 8 Boolean "decisions" (aka: flags), there is a need to isolate each given bit for conversion to a Boolean variable...
If that's the actual goal, bitshifting is neither necessary nor useful: Just use a bitwise & with the desired bit, which will give you either 0 or a number with that bit set. 0 is falsy, the number with a bit set is truthy. You can either use that as-is, or force it to boolean via !!flag or Boolean(flag):
Here's your bitParser function using bitmasking:
var bitParser = function (_nTestByte, _nBitOrdinal) {
return !!(_nTestByte & Math.pow(2, _nBitOrdinal));
};
console.log(bitParser(0b10100101, 2)); // true
console.log(bitParser(0b10100101, 1)); // false
Rather than doing the Math.pow every time, of course, we'd probably be better off with a lookup table:
var bits = [
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00100000,
0b01000000,
0b10000000
];
var bitParser = function (_nTestByte, _nBitOrdinal) {
return !!(_nTestByte & bits[_nBitOrdinal]);
};
console.log(bitParser(0b10100101, 2)); // true
console.log(bitParser(0b10100101, 1)); // false
From your question I took
console.log((0b10100101 << 26) >> 31); //instead of 1, returns -1.
And to answer your question why it returned -1 instead of 1
You need to do unsigned right shift >>> instead of signed one >>
console.log((0b10100101 << 26 ) >>>31);
Yes it can, and what you're doing is almost correct.
Integers are represented as a 32bit binary number, with the leftmost bit representing the sign (it's 1 if the number is negative and 0 if the number is positive). Lets look at some of the numbers' representations:
//last 31 digits keeps increasing as the number decreases
// ...
-2 => 0b11111111111111111111111111111110
-1 => 0b11111111111111111111111111111111
0 => 0b00000000000000000000000000000000
1 => 0b00000000000000000000000000000001
2 => 0b00000000000000000000000000000010
// ...
// last 31 digits keep increasing as the number increases
Now, what you're having (0b10100101 << 26) should give you 10010100000000000000000000000000, which you'd expect to be a big negative number (because the left-most bit is 1). Then right afterwards, you have >> 31 which you're expecting to strip off all 31 bits and leave you with the left-most bit.
That should work, but it's not what's happening. And why is that? It's because the people who came up with ECMAScript thought it would make more sense if 4 >> 1 returns 2 and -4 >> 1 returns -2.
4 >> 1 // returns 2 which is 0b00000000000000000000000000000010
0b0000000000000000000000000000000100 >> 1 // returns 2, same
-4 >> 1 // returns -2, which is 0b11111111111111111111111111111110
But -4 is 0b11111111111111111111111111111100, and for your purposes right shifting it by 1 should yield 0b01111111111111111111111111111110 (big positive number, since left-post bit is 0), and that's not -2!
To overcome that, you can use the other right shift operator which doesn't care about about the sign: >>>. -4 >>> 1 is 2147483646 which is what we want.
So console.log((0b10100101 << 26) >>> 31); gives you 1, which is what you want. You can also keep using >> and regarding any negative outcome to be a result of 1 being the chosen bit.
The most simple way to achieve your actual need is to use simple conditions rather than trying to isolate bits.
var bitParser = function (_nTestByte, _nBitOrdinal) {
return (_nTestByte & _nBitOrdinal);
};
console.log(bitParser(6, 2) ? true : false); // true
console.log(bitParser(6, 1) ? true : false); // false
I adapted the console.log() expression in a way that may seem complicated.
It's only to really show the logical result at this step, while I didn't choose to use !! inside of the function, so returning a truly/falsy value rather than true|false.
Actually this way keeps all the most simple possible, because the expected use else where in the code is if (bitParser(...)), which automatically casts the result to boolean.
BTW, this works whatever is the _nTestByte size (may be more than 1 byte).
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?
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'.
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.)
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.
That is the unsigned right bit shift operator. The difference between this and the signed right bit shift operator, is that the unsigned right bit shift operator (>>>) fills with zeroes from the left, and the signed right bit shift operator (>>) fills with the sign bit, thus preserving the sign of the numerical value when shifted.
Driis has sufficiently explained what the operator is and what it does. Here's the meaning behind it/why it was used:
Shifting any direction by 0 does returns the original number and will cast null to 0. It seems that the example code that you are looking at is using this.length >>> 0 to ensure that len is numeric even if this.length is not defined.
For many people, bitwise operations are unclear (and Douglas Crockford/jslint suggests against using such things). It doesn't mean that its wrong to do, but more favorable and familiar methods exist to make code more readable. A more clear way to ensure that len is 0 is either of the following two methods.
// Cast this.length to a number
var len = +this.length;
or
// Cast this.length to a number, or use 0 if this.length is
// NaN/undefined (evaluates to false)
var len = +this.length || 0;
>>> is the unsigned right shift operator (see p. 76 of the JavaScript 1.5 specification), as opposed to the >>, the signed right shift operator.
>>> changes the results of shifting negative numbers because it does not preserve the sign bit when shifting. The consequences of this is can be understood by example, from an interpretter:
$ 1 >> 0
1
$ 0 >> 0
0
$ -1 >> 0
-1
$ 1 >>> 0
1
$ 0 >>> 0
0
$ -1 >>> 0
4294967295
$(-1 >>> 0).toString(16)
"ffffffff"
$ "cabbage" >>> 0
0
So what is probably intended to be done here is to get the length, or 0 if the length is undefined or not an integer, as per the "cabbage" example above. I think in this case it is safe to assume that this.length will never be < 0. Nevertheless, I would argue that this example is a nasty hack, for two reasons:
The behavior of <<< when using negative numbers, a side-effect probably not intended (or likely to occur) in the example above.
The intention of the code is not obvious, as the existence of this question verifies.
Best practice is probably to use something more readable unless performance is absolutely critical:
isNaN(parseInt(foo)) ? 0 : parseInt(foo)
Two reasons:
The result of >>> is an "integral"
undefined >>> 0 = 0 (since JS will try and coerce the LFS to numeric context, this will work for "foo" >>> 0, etc. as well)
Remember that numbers in JS have an internal-representation of double.
It's just a "quick" way of basic input sanity for length.
However, -1 >>> 0 (oops, likely not a desired length!)
Sample Java Code below explains well:
int x = 64;
System.out.println("x >>> 3 = " + (x >>> 3));
System.out.println("x >> 3 = " + (x >> 3));
System.out.println(Integer.toBinaryString(x >>> 3));
System.out.println(Integer.toBinaryString(x >> 3));
Output is the following:
x >>> 3 = 536870904
x >> 3 = -8
11111111111111111111111111000
11111111111111111111111111111000
I am implementing decoding of BER-compressed integers and recently I've found a weird JavaScript behavior related to bitwise operations with big integers.
E.g.:
var a = 17516032; // has 25 bits
alert(a << 7) // outputs -2052915200
alert(a * 128) // outputs 2242052096
alert(2242052096 >> 16) // outputs -31325
alert(2242052096 / 65536) // outputs 34211
While the first workaround (multiplication instead of left shift) is acceptable, the second isn't.
Why it happens? How to bear with it?
17516032 in binary is 00000001000010110100011000000000. Shifting to the left by 7 gives you 10000101101000110000000000000000. This is equal to -2052915200 in two's complement (which is how almost all computers represent negative numbers).
>> is a signed right shift. That means that the leftmost bit (which determines the sign of a number) will be shifted into the left side.
e.g.
1100 >> 2 == 1111
0111 >> 2 == 0001
If you want to do an unsigned shift (which ignores the sign bit), use >>> which will zero-fill the left end of the bitstring.
Bitwise operators work on 32 bit integers, while multiplication and division works on floating point numbers.
When you shift a number, it's converted from a floating point number to a 32 bit integer before the operations, and converted back to a floating point number after the operation. The number 2242052096 has the 32nd bit set, so it is a negative number when converted to and from a 32 bit integer.
The >> right shift operator doesn't change the sign of the value, i.e. the bits that are shifted in from the left have the same value as the sign bit. Use the >>> right shift operator to shift in zero bits instead.
Reference: MDN: Bitwise operators
(2242052096 / 65536) == (2242052096 >>> 16)
Note the different shift.
Javascript normally represents numbers as (double-precision) floating point.
Almost all bitwise operations convert to a signed 32-bit integer, do whatever they're going to do, then treat the result as a signed 32-bit integer when converting back.
The exception is >>> which treats the result as an unsigned 32-bit integer when converting back.
So:
right shifts can be made to work simply by using >>> instead of >> ;
a * 128 gives the expected answer because it's never converted to a signed 32-bit integer in the first place - it's just a floating-point multiplication;
a << 7 gives an unexpected answer because it's converted to a signed 32-bit integer, and then you shift a 1 into the sign bit, resulting in a negative signed 32-bit value.
There isn't a <<<, but if you want to write your left shift as a shift, you can use
(a << 7) >>> 0
to get the expected answer (the >>> 0 effectively casts the signed 32-bit value to an unsigned 32-bit value).
What does this: >> mean in JavaScript?
Seen in this context:
document.onkeydown = document.onkeyup = function(e,v,y,k) {
(i=e.keyCode-37)>>2 || (keys[i] = e.type[5]&&1||(0))
}
>> is the bitwise right shift operator.
For example: 4 >> 1 equals 2 because 4 is 100 in binary notation, which is shifted one bit to the right, giving us 10 = 2
Javascript Bitwise Operators
Left shift a << b Shifts a in binary
representation b (< 32) bits to the
left, shifting in zeros from the
right.
Sign-propagating right shift a >>
b Shifts a in binary representation b
(< 32) bits to the right, discarding
bits shifted off.
(i=e.keyCode-37)>>2
This code is discarding the two least significant bits of i (similar to dividing by 4), and comparing the result to zero. This will be false when the key pressed is 37-40 (arrow keys), and true otherwise.
It's the Bitwise shift operator (see here).
Now, as to exactly what it's doing here I'm not sure... I'm sure some of our larger-brained bretheren that actually finished college could help us out with that. ;^)