2

Now I'm try to convert some js code into java , there is a problem:

In js

46022*65535 = 3016051770

and

(46022*65535)|7867 = -1278910789

In java

46022*65535 = -1278915526 this is overflow

46022L*65535L = 3016051770L this is the same result to js

(46022*65535)|7867 = -1278910789 this one and the one below is the problem

(46022L*65535L)|7867L = 3016056507L

So , why the | operator will make two positive number to be nagtive number? What's the different between java and js when dealing with the int and long to do this operation?

And then , how to write java code compatible with js in this situation ?

Attention:I know the range of int and long , my problem is |.

More problems :

According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators & is also 32bit operation, then: In js

2996101485 & 65535 = 57709

In java

2996101485 is overflow to int so I use double to store it and cast it into int when I need to do AND.

double a = 2996101485l;

double b = 65535;

int c = (int) a & (int) b; Now c = 65535

But if I use long to cast :

long c = (long) a & (long) b; Now c = 57709

So , just simply cast double into int will cause problems. And I want to know why?

I got the problem , 2996101485 can be present in 32bit in js and in java it should be long. So I write functions to convert those operations , for example, & should use this java function to run give same result in js:

private double doOR(double x, double y) {
    if (x > Integer.MAX_VALUE && x <= 1l << 32) {
        if (y > Integer.MAX_VALUE && y <= 1l << 32) {
            return (long) x | (long) y;
        } else {
            return (long) x | (int) y;
        }
    } else {
        return (int) x | (int) y;
    }
}
Community
  • 1
  • 1
zzy
  • 1,771
  • 1
  • 13
  • 48

2 Answers2

2

You should use long instead.

System.out.println(46022L*65535L); // = 3016051770

Java has ints and longs.

    System.out.println(Integer.MAX_VALUE);  // = 2147483647
    System.out.println(Long.MAX_VALUE);  // = 9,223,372,036,854,775,807

As for the language difference, I can only attribute it to different precisions between the languages. If you see this question, you'll see the largest number in JS is 9,007,199,254,740,992. That's a guess, it might be for another reason.

Community
  • 1
  • 1
Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
2

The problem is that while numbers in JavaScript have roughly 53-bit precision (they appear to be based on floating point doubles), the bitwise OR operates on only 32 bits.

Bitwise operators treat their operands as a sequence of 32 bits (zeroes and ones), rather than as decimal, hexadecimal, or octal numbers.

This means that when working with arithmetic, long will get you the JavaScript-like arithmetic (with numbers such as yours), since Java ints will overflow; but when working with bitwise operations, int will get you the JavaScript-like results, since then both platforms are operating on 32-bit numbers.

Community
  • 1
  • 1
yshavit
  • 42,327
  • 7
  • 87
  • 124
  • So when I use OR operates , js let the number be 32bit precision? – zzy Mar 12 '15 at 01:24
  • Essentially, yes. At least, what's what it appears from what I've read! I don't know JavaScript as well as I know Java. – yshavit Mar 12 '15 at 01:28
  • I see your update, if I just cast `long` into `int` before I do the OR operates , will it run like js? – zzy Mar 12 '15 at 01:28
  • That should work, yes -- but make sure to cast _all_ of the operands to `int`, or else just a single one will cause them all to get promoted to `long`! – yshavit Mar 12 '15 at 01:30
  • btw, that's just what you had in your third Java snippet, `(46022*65535)|7867 = -1278910789` -- in that snippet, all the operands are `int`. – yshavit Mar 12 '15 at 01:32
  • Yes , I will be careful ,there just one line has this problem. :-) – zzy Mar 12 '15 at 01:35
  • I have found more problems relate to the cast ,could you point the problem out? – zzy Mar 12 '15 at 03:34