11

I want to split a 64bit integer into two 32bit integers:

var bigInt = 0xffffff;

var highInt = bigInt >> 8 // get the high bits 0xfff
var lowInt = bigInt // cut of the first part (with &)?

console.log(highInt); // 0xfff
console.log(lowInt); // 0xfff

// set them together again
var reBigInt = (highInt << 8) + lowInt;

Unfortunately neither getting the highInt nor getting the lowInt works... Could somebody give me the answer how I need to use the bitwise operators?

regards

bodokaiser
  • 15,122
  • 22
  • 97
  • 140

3 Answers3

7

EDIT JavaScript represents integers using IEEE double precision format, so there is no way to store arbitrary 64 bit integers without loss of precision, except through custom big integer libraries. Bitwise operations on potentially cropped values obviously make no sense.


In general, for languages that do support 64 bit integers:

A 64-bit pattern of ones is 0xffffffffffffffff. To extract the upper 32 bits, you need to shift by 32: >> 32. To extract the lower 32 bit, just and them with 32 ones: & 0xffffffff.

You got the principle right - your arithmetic on how many bits to shift or mask is just wrong.

Community
  • 1
  • 1
Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • can it be that javascript does not support such big numbers 0xffffffffffffffff >> 32 always returns 0? – bodokaiser Feb 06 '13 at 14:55
  • I'm sorry, I forgot about JavaScript's limited 64 bit support. Edited. – Alexander Gessler Feb 06 '13 at 14:58
  • 2
    this is a very bad idea, if the 31th bit was 1, you'll get a negative number and that's certainly not what you want. just use a modulo operation: number % Math.pow(2, 32) – nraynaud Aug 18 '16 at 20:11
6

In JavaScript all numbers are represented using 53 bits. JavaScript uses floating point representation to store all numbers internally, which means that integers are stored as floating point numbers (mantissa has 53 bits)

So with 53 bits we can represent max 2^53 = 9007199254740992.

But you cannot use right shift and AND binary operations to extract lower 32 bits and higher 21 bits even from 53 bit numbers.

The reason is when we apply binary operator on any number - Javascript first convert that number to 32 bit signed number, apply the binary operation and return the result. This means any bit that sits in position higher than 32 will be discarded.

I have used following approach to extract the higher (21 bit) and lower (32 bits) portions from a positive number <= 2^53.

var bigNumber = Math.pow(2, 53); // 9007199254740992
var bigNumberAsBinaryStr = bigNumber.toString(2); // '100000000000000000000000000000000000000000000000000000'
// Convert the above binary str to 64 bit (actually 52 bit will work) by padding zeros in the left
var bigNumberAsBinaryStr2 = ''; 
for (var i = 0; i < 64 - bigNumberAsBinaryStr.length; i++) {
    bigNumberAsBinaryStr2 += '0'; 
}; 

bigNumberAsBinaryStr2 += bigNumberAsBinaryStr;

var lowInt = parseInt(bigNumberAsBinaryStr2.substring(0, 32), 2);
var highInt = parseInt(bigNumberAsBinaryStr2.substring(32), 2);

Just to confirm above logic is correct, lets try building the bigNumber from two parts

Assert((lowInt * Math.pow(2, 32) + highInt) === bigNumber);
  • 1
    I don't think you need to do all that string manipulation As long as lowInt is less than 2 ** 21 this should work, right? `const getLow = (bigInt) => Math.floor(bigInt / (2 ** 32))` `const getHigh = (bigInt) => bigInt - getLow(bigInt) * (2 ** 32)` `const getBig = (lowInt, highInt) => lowInt * (2 ** 32) + highInt` – Maybe Julius Feb 03 '20 at 20:28
0

My way of doing it

In JavaScript, you can only have integers between 9007199254740991 and -9007199254740991 inclusive. That uses 53 bits. So what you are looking for is the upper 21 bits and the lower 32 bits

Check out Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER.

Also, you can't use bit shifting on numbers larger than 32 bits because JavaScript simply discards them. But, if you convert the value to a hex string, you can then parse the values using parseInt. Just know that the code below only works on values between 0 and 9007199254740991 inclusive. It won't work on negative numbers... well not without some more logic to check for a negative number and handle that case appropriately

// Convert the number to a hex string
let string = number.toString(16)

// Zero pad the string up to 14 characters
string = "0".repeat(14 - string.length) + string

// Parse the high and low numbers
let high = parseInt(string.substring(0, 6), 16)
let low = parseInt(string.substring(6), 16)
Ray Perea
  • 5,640
  • 1
  • 35
  • 38