Question

Here is outputs from Google Chrome Javascript Console.
http://i.stack.imgur.com/gefcZ.png

Here is outputs from DrJava Java Console.
http://i.stack.imgur.com/bQ7hS.png

My Javascript code is

(baseCPUCyclesPerIteration - CPUCyclesTotalRoundoff) | 0

Seems to compile fine in Java if both variables are integers but apparently they are doubles in javascript. Even though

typeof baseCPUCyclesPerIteration reveals "number"

The results make it pretty obvious it's a double datatype. I don't understand why bitwise OR 0 works on a double in Javascript but doesn't work on Java double's.

Seems the purpose of the | 0 is just to trim of the decimal points in double datatype. I'm guessing in Java the equivalent will be (int) or (long) cast is this correct? or the bitwise | 0 does more then just trim of the decimal point in javascript?

Edit: ya | 0 doesn't just trim in javascript just ran this. 8899811111.111113453456754645 | 0 got back 309876519.
(Although I passed the double limit lol still tries to compute it in javascript, I'm guessing this is where the overflows happen).

Was it helpful?

Solution

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:

  1. Let number be the result of calling ToNumber on the input argument.
  2. If number is NaN, +0, −0, +∞, or −∞, return +0.
  3. Let posInt be sign(number) * floor(abs(number)).
  4. 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.
  5. 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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top