Reputation: 547
In Javascript, logical shift works differently from other languages.
var value = 1543812808507000000
var lowBits = value >>> 0
this is javascript code. And the result is 3804366080. But when we developed this logic in java or c, the result was 3804366016.
Which one is correct? How does Logical shifting work in JS?
Upvotes: 4
Views: 195
Reputation: 25526
According to mozilla JS reference:
The MAX_SAFE_INTEGER constant has a value of 9007199254740991 (9,007,199,254,740,991 or ~9 quadrillion). The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent numbers between -(253 - 1) and 253 - 1.
As denoted in the comments already, your input number of 1543812808507000000 is larger than the largest safe integer.
Thus rounding occurs on the JavaScript side.
In contrast, C and Java both use (exact) integral math (below the C version):
unsigned long long n = 1543812808507000000ULL;
n &= 0x00000000ffffffffULL;
printf("%llu\n", n);
Alternative calculation:
n %= 0x0000000100000000ULL;
So the C/Java output is the mathematically correct one.
You have great chances to produce the same result in C using floating point math as well:
uint64_t n64 = 1543812808507000000ULL;
double d = n64; // on conversion, rounding occurs!
uint32_t n32 = d; // back to 32 bit, most significant bits dropped
printf("%lu\n", (unsigned long)n32);
For completeness: IEEE754 describes different rounding algorithms, and C standard does not mandate a specific one – actually, it even does not mandate IEEE754 at all. But as both JS and C directly use the same underlying hardware (and all modern hardware follows IEEE754 with same default rounding), this is not of practical relevance...
If you wonder about the cast: uint32_t
is likely to be typedef
-ed as unsigned int
, but not necessarily (could be unsigned long
or even unsigned short
as well, all legal according to C standard). For unsigned long
, though, C mandates a range to be covered such that we need at least 32 bit, so by casting and using %lu
format specifier we avoid undefined behaviour due to mismatching format specifier and data type without changing the outcome.
Upvotes: 3