skip to Main Content

In my program I generate the code from the incoming number "int". Sometimes I need to do the reverse action, translate the code into a number. With small numbers, it works fine.

const int = 10203040

const code1 = (int >> 16) & 0xFFFF

const code2 = int & 0xFFFF

const myCode = `${code1},${code2}` // 155,44960

const returnInt = ((code1 & 0xFFFF) << 16) + (code2 & 0xFFFF) // 10203040

Problems arise when working with large numbers. What to use to get the number 9007199254740991 again in the example below?

const int = 9007199254740991

const code1 = (int >> 16) & 0xFFFF

const code2 = int & 0xFFFF

const myCode = `${code1},${code2}` // 65535,65535

const returnInt = ((code1 & 0xFFFF) << 16) + (code2 & 0xFFFF) // -1

Tried to work with the library long.js, but failed, lack of knowledge

2

Answers


  1. The problem here is that two 16-bit chunks are not enough to store a 53-bit number. In order to store a number as large as 9007199254740991, you would need at least three 16-bit chunks.

    const int = BigInt(9007199254740991);
    
    const code1 = (int >> 32n) & 0xFFFFn;
    const code2 = (int >> 16n) & 0xFFFFn;
    const code3 = int & 0xFFFFn;
    
    const myCode = `${code1},${code2},${code3}`; // 262143,65535,65535
    
    const returnInt = (BigInt(code1) << 32n) + (BigInt(code2) << 16n) + BigInt(code3); // 9007199254740991n
    

    Using Long

    const Long = require('long');
    
    const int = Long.fromString('9007199254740991');
    
    const code1 = (int.shiftRightUnsigned(32)).and(0xFFFF);
    const code2 = (int.shiftRightUnsigned(16)).and(0xFFFF);
    const code3 = int.and(0xFFFF);
    
    const myCode = `${code1},${code2},${code3}`; // 262143,65535,65535
    
    const returnInt = (code1.shiftLeft(32)).add(code2.shiftLeft(16)).add(code3); // 9007199254740991
    
    Login or Signup to reply.
  2. Your code is splitting the input number into two 16-bit chunks (by masking it with 0xFFFF, which has 16 bits set). In two 16-bit chunks, you can store a 32-bit (integer) number. 9007199254740991 is a 53-bit number, so two 16-bit chunks are not enough to store it.

    Another issue is that the bitwise operators in JavaScript implicitly truncate their inputs to 32 bits. That’s the part where using BigInts helps — but you’ll still have to use more than two 16-bit chunks.

    For example, you could use four 16-bit chunks, then you can store up to 64-bit numbers. That would look like this:

    const int = 9007199254740991n;
    const code1 = (int >> 48n) & 0xFFFFn;  // bits 49 - 64
    const code2 = (int >> 32n) & 0xFFFFn;  // bits 33 - 48
    const code3 = (int >> 16n) & 0xFFFFn;  // bits 17 - 32
    const code4 = int & 0xFFFFn;           // bits 1 - 16
    
    const myCode = `${code1},${code2},${code3},${code4}`  // '31,65535,65535,65535'
    
    const returnInt = (code1 << 48n) + (code2 << 32n) + (code3 << 16n) + code4;
    

    (You don’t need to mask the chunks again when computing returnInt.)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search