Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this bitwise operation is failing in Javascript

Tags:

javascript

Some one please shed light on this when doing bitwise operation in javascript I get:

65527|34359738368 =>65527

Is it possible to handle this in javascript ?

From mysql command line:

select 65527|34359738368 ;
+-------------------+
| 65527|34359738368 |
+-------------------+
|       34359803895 |
+-------------------+

And more importantly its less than 2 ^ 36

select (65527|34359738368)< pow(2,36);
+--------------------------------+
| (65527|34359738368)< pow(2,36) |
+--------------------------------+
|                              1 |
+--------------------------------+

What I read from this SO Q is that int in javascript support max 2^53 value. I might be missing sth

like image 218
sakhunzai Avatar asked Feb 13 '14 07:02

sakhunzai


2 Answers

You linked to the answer yourself:

Note that the bitwise operators and shift operators operate on 32-bit ints.

like image 103
Tim Pietzcker Avatar answered Sep 29 '22 02:09

Tim Pietzcker


As Tim has already pointed out, bitwise operations in JavaScript use 32-bit numbers. One solution (and probably the easiest) is to use a bignum library that supports bitwise operations, such as this one: https://www.npmjs.org/package/bignum.

Another way to do it would be to break the number into words, and do the operations on the words separately, old-school style:

var a = 65527;
var b = 34359738368;
var wordSize = 4294967296;  // 2^32
var ah = Math.floor(a/wordSize);
var al = a - ah*wordSize;
var bh = Math.floor(b/wordSize);
var bl = b - bh*wordSize;

var xh = ah | bh;
var xl = al | bl;
var x = xh*wordSize + xl;

All we're doing is breaking the two operands into two words (high and low), doing the operations on the words, yielding our result (x) as a high and a low word, then recombining them to make a word.

You could, of course, bundle this into a neat function:

function or64(a,b){
    var w64 = 18446744073709552000;  // 2^64
    var w32 = 4294967296;            // 2^32
    if(a>w64 || b>w64)
        throw new Error('operands cannot exceed 64 bits');
    var ah = Math.floor(a/w32);
    var al = a - ah*w32;
    var bh = Math.floor(b/w32);
    var bl = b - bh*w32;
    return (ah|bh)*w32 + (al|bl);
}
like image 45
Ethan Brown Avatar answered Sep 29 '22 00:09

Ethan Brown