In javascript, all bitwise operators will cast decimal numbers to 32 bit integers. It acts like floor
for positive numbers and ceil
for negative numbers. Things like |0
or ~~
are often used as tricks to cast numbers to integer in JavaScript.
To explain the overflow you're seeing, we can look at the specifications for how Javascript converts numbers to int32: http://es5.github.io/#x9.5
The abstract operation ToInt32 converts its argument to one of 2^32 integer values in the range −2^31 through 2^31−1, inclusive. This abstract operation functions as follows:
- Let number be the result of calling ToNumber on the input argument.
- If number is NaN, +0, −0, +∞, or −∞, return +0.
- Let posInt be sign(number) * floor(abs(number)).
- Let int32bit be posInt modulo 2^32; that is, a finite integer value k of Number type with positive sign and less than 2^32 in magnitude such that the mathematical difference of posInt and k is mathematically an integer multiple of 2^32.
- If int32bit is greater than or equal to 2^31, return int32bit − 2^32, otherwise return int32bit.
So, to reproduce this behavior, you would have to reproduce this logic.
Edit: Here's how Mozilla's Rhino engine does it in Java: (as per the github link supplied by user3435580)
public static int toInt32(double d) {
int id = (int)d;
if (id == d) {
// This covers -0.0 as well
return id;
}
if (d != d
|| d == Double.POSITIVE_INFINITY
|| d == Double.NEGATIVE_INFINITY)
{
return 0;
}
d = (d >= 0) ? Math.floor(d) : Math.ceil(d);
double two32 = 4294967296.0;
d = Math.IEEEremainder(d, two32);
// (double)(long)d == d should hold here
long l = (long)d;
// returning (int)d does not work as d can be outside int range
// but the result must always be 32 lower bits of l
return (int)l;
}