1

I have the following Java code:

long num = 3482085570325547757;
// Discard all but the highest priority 31 bits
int result = (int) (num >>> 33); // Returns 405368112

I am trying to do the equivalent in Javascript (using the https://github.com/oracle/graaljs engine), however, it is not giving me the same result as the Java code:

const num = 3482085570325547757;
// Discard all but the highest priority 31 bits
const result = num >>> 33; // Returns 1281508608

I thought it may have to do with the way GraalJS stores numbers internally as ints and doubles? I've tried explicitly casting to int as well using the below but it also gave me a different result to the Java code:

const Long = Java.type('java.lang.Long');
const String = Java.type('java.lang.String');
const BigInteger = Java.type('java.math.BigInteger');
const num = 3482085570325547757;
// Discard all but the highest priority 31 bits
const result = BigInteger.valueOf(num >>> 33).intValue(); // Returns 1281508608
rmf
  • 625
  • 2
  • 9
  • 39

1 Answers1

2

First off, your Java example doesn't compile. Long literals require an L (or l) suffix:

long num = 3482085570325547757L;

Then, JavaScript can't store that number with full accuracy.

const num = 3482085570325547757;
console.log(num); // Displays 3482085570325547500

The maximum integer it can store is 9007199254740991 (Number.MAX_SAFE_INTEGER).

Using Java's BigInteger like you did like that won't work, because you have already lost accuracy before creating the BigInteger. You'd need to use a string to correctly create the BigInteger (or JavaScript's BitInt, or the n suffix).

However that isn't really helpful either, because >>> doesn't make sense on them. Quote from Java's BigInteger documentation:

The unsigned right shift operator (>>>) is omitted since this operation only makes sense for a fixed sized word and not for a representation conceptually having an infinite number of leading virtual sign bits.

The same is true for JavaScript's BigInt.

You however can use the normal right shift (>>) operator with BigInt:

const num = BigInt("3482085570325547757");
const bigIntResult = num >> BigInt(33); 
const result = Number(bigIntResult); // Convert to normal number

Or

const num = 3482085570325547757n;
const bigIntResult = num >> 33n; 
const result = Number(bigIntResult); // Convert to normal number

Or the shiftRight() method of Java's BigInteger (untested, because I don't have GraalJS setup):

const BigInteger = Java.type('java.math.BigInteger');
const num = new BigInteger("3482085570325547757");
const result = num.shiftRight(33).intValue();

See also:

David Conrad
  • 15,432
  • 2
  • 42
  • 54
RoToRa
  • 37,635
  • 12
  • 69
  • 105