I'm fiddling around with bitwise operators in JavaScript and there is one thing I find remarkable.
The bitwise or operator returns 1 as output bit if one of the two input bits are 1. So doing x | 0 always returns x, because | 0 has no effect:
( 1 | 0 ) === 1
( 0 | 0 ) === 0
However, when I calculated Infinity | 0, I got 0. This is surprising in my opinion, because by the above one should get Infinity. After all, ( x | 0 ) === x.
I cannot find where in the ECMAscript specification this is explicitly defined, so I was wondering what exactly implies that ( Infinity | 0 ) === 0. Is is perhaps the way Infinity is stored in memory? If so, how can it still be that doing a | 0 operation causes it to return 0 whereas | 0 should not do anything?
Bitwise operators work on integers only.
Infinity is a floating-point value, not an integer.
The spec says that all operands of bitwise operations are converted to integers (using the ToInt32 operation) before performing the operation.
The ToInt32 operation says:
If number is NaN, +0, −0, +∞ or –∞ return +0.
Doing math and other operations that expect integers with NaN and Infinity is usually a bad idea. How would you set/clear a bit from Infinity?
Actually, bit-wise operations are only defined for integers - and integers do not have NaN or Infinity.
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
I have just found that in ES6 there's a new math method: Math.trunc.
I have read its description in MDN article, and it sounds like using |0.
Moreover, <<0, >>0, &-1, ^0 also do similar things (thanks #kojiro & #Bergi).
After some tests, it seems that the only differences are:
Math.trunc returns -0 with numbers in interval (-1,-0]. Bitwise operators return 0.
Math.trunc returns NaN with non numbers. Bitwise operators return 0.
Are there more differences (among all of them)?
n | Math.trunc | Bitwise operators
----------------------------------------
42.84 | 42 | 42
13.37 | 13 | 13
0.123 | 0 | 0
0 | 0 | 0
-0 | -0 | 0
-0.123 | -0 | 0
-42.84 | -42 | -42
NaN | NaN | 0
"foo" | NaN | 0
void(0)| NaN | 0
How about Math.trunc(Math.pow(2,31)) vs. Math.pow(2,31) | 0
Bitwise operations are performed on signed 32-bit integers. So, when you do Math.pow(2, 31) you get this representation in bits "10000000000000000000000000000000". Because this number has to be converted to signed 32-bit form, we now have a 1 in the sign bit position. This means that we are looking at a -eve number in signed 32-bit form. Then when we do the bitwise OR with 0 we get the same thing in signed 32-bit form. In decimal it is -2147483648.
Side note: In signed 32-bit form the range of decimals that can be represented in binary for is [10000000000000000000000000000000, 01111111111111111111111111111111]. In decimal (base 10) this range is [-2147483648, 2147483647].
In many programming languages with bitwise operators, attempting to do a bitwise operation on a non-integer is a type error:
>>> # Python
>>> 1 << 0; 1.2 << 0
1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for <<: 'float' and 'int'
In ECMA-262, a Number is a double-precision 64-bit binary format IEEE 754. In other words, there are no integers in JavaScript. As long as the values you're dealing with fit within -(Math.pow(2,32)) and Math.pow(2,31) then the bitwise operations are a fast way to truncate floating point values. All of the different bitwise operations do different things, but in every example here they're essentially doing an identity operation. The critical difference is that JavaScript does a ToInt32 operation on the value before doing the nothing else part.
Bitwise identity operations:
i | 0 // For each bit that is 1, return 1|0. For each bit that is 0, return 0|0.
i ^ 0 // xor, but effectively same as previous.
i << 0 // Shift the value left zero bits.
i >> 0 // Shift the value right zero bits.
i & -1 // Identity mask
~~i // Not not - I had forgotten this one above.
I'm looking at some Javascript code that is:
if ( a>2 | b>4 ) { ... }
(ignore the ... above). What's the | doing? I assume it's logical OR, but all the references I could find online speak about ||, and I can't find anything mentioning just |. Thanks in advance
It's the bitwise or. || is logical or.
The bitwise or (|) coerces the values to 32 bit integers and returns the 32 bit integer with each bit set to 1 if either of the two bits in the corresponding locations is 1 and 0 if they are both 0.
Logical or (||) evaluates to the first value if it's not falsey, otherwise it evaluates to the second value.
You almost definitely want || instead of |.
The difference between || and | is already explained in the other answers.
However, in the above code, | has the same effect as || due to type conversion.
true and false are mapped to 1 and 0 and we have
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
1 | 1 = 1
The same goes into the other direction, 1 evaluates to true and 0 to false.
So in this example,
if ( a>2 | b>4 )
will have the same result as
if ( a>2 || b>4 )
Note: This really only works with the two values 0 and 1.
This could be some kind of micro-optimization.
Update:
However, a short test reveals that using the bitwise OR for this purpose is way slower (at least in Chrome 9):
http://jsperf.com/js-or-test
Conclusion: Don't use it instead of logical OR :) Mostly likely someone forgot the second | and is just lucky that the code produces the same result.
Use boolean operators for boolean operations and bitwise operators for fancy bit masking. This might be worth reading: MDC - Bitwise Operators.
Single | is a bitwise-OR while double (||) is a logical-OR.
Bitwise-OR takes the binary representation of the two source values and ORs them together so that if either of the values has a bit set, the resulting value's bit will also be set (repeat for all the bits in the two source values).
Logical-OR concerns itself with true and false values (where 0 maps to false and non-zero maps to true - that's simplified, JavaScript has more specific rules). If either source value is true then the result is true.
Looks like second pipe just got lost, otherwise it is a smelly hack. See what really happens:
if ( Boolean( Number(a>2) | Number(b>4) ) ) { ... }
(Number is special here because bitwise operators are working with 32-bit integers)
It works because Number(true) === 1 && Number(false) === 0.
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 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