23

I need to bitwise shift a value 64 times in JavaScript. But JavaScript starts rounding after 32.

For example:

for(var j = 0; j < 64; j++)
{
    mask = mask << 1;
    console.log(mask);
}

This prints value from 0 to 1073741824 but then rounds of and starts printing 0.

Danilo Valente
  • 11,270
  • 8
  • 53
  • 67
sandi
  • 233
  • 1
  • 2
  • 4

3 Answers3

37

"In Java, the bitwise operators work with integers. JavaScript doesn't have integers. It only has double precision floating-point numbers. So, the bitwise operators convert their number operands into integers, do their business, and then convert them back. In most languages, these operators are very close to the hardware and very fast. In JavaScript, they are very far from the hardware and very slow. JavaScript is rarely used for doing bit manipulation." - Douglas Crockford, Javascript: The Good Parts

The point is that you don't really have any reason to use bitwise operators. Just multiply or divide by 2^numbits.

Your code should be:

for(var j = 0; j < 64; j++) {
 mask = mask * 2;
 console.log(mask);
}

Or generally:

function lshift(num, bits) {
    return num * Math.pow(2,bits);
}

You get the idea.

Community
  • 1
  • 1
itsadok
  • 28,822
  • 30
  • 126
  • 171
  • 4
    Careful: the code above works, but only up to the 52bit mantissa - not 64 bits ! If you set mask=1; and then run the the code above, it ends with 18446744073709552000 - but 2^64 is actually 18446744073709551616. The last 4 digits are blanked out because 52 bits can't hold 64 bits :-( – Axel Podehl Aug 20 '18 at 09:15
12

JavaScript stores all its numbers as 64 bit initally, but as soon as you start using bitwise operators the interpreter converts the number to a 32 bit representation..

Bitwise operators are a bit hacky in JS and so annoyingly you will probably have to do something a bit more clever, like write your own 64 bit functions.

adam
  • 22,404
  • 20
  • 87
  • 119
  • 4
    Javascript does not have integers as a visible type in the language; all numbers are double-precision (64-bit) floating point. Those can only hold up to 53 bits of mantissa, which a 64-bit integer won't fit into. So when it does the internal conversion to integer and back, it only uses 32 bits. – Mark Reed Aug 11 '16 at 15:38
4

With BigInt you can use bitwise operators, except >>>.

For example:

console.log(1n << 32n); // 4294967296n
console.log(1n << 40n); // 1099511627776n

console.log((1n << 40n).toString(2)); // 1 00000000 00000000 00000000 00000000 00000000

BigInt is a 64-bit signed integer.