0

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

Rohad Bokhar
  • 104
  • 9
smeninick
  • 1
  • 1
  • https://stackoverflow.com/questions/307179/what-is-javascripts-highest-integer-value-that-a-number-can-go-to-without-losin, try BigInt – Tom Fan Apr 20 '23 at 04:38
  • Late to the thread, but another option is [BigUint64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array) for those stumbling your way here... – Trentium May 15 '23 at 20:33

2 Answers2

1

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.)

jmrk
  • 34,271
  • 7
  • 59
  • 74
-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
BIS Tech
  • 17,000
  • 12
  • 99
  • 148
  • didn't work myCode - 65535,65535 returnInt - 4294967295n – smeninick Apr 20 '23 at 06:41
  • 1
    Your first paragraph, while correct, is missing the point: neither `MAX_SAFE_INTEGER` nor the 32-bit truncation of bitwise operators are directly responsible for the problem here. Two 16-bit chunks simply aren't enough to store a 53-bit number, with or without BigInts. Also, it's preferable to use `16n` notation instead of `BigInt(16)`, because it's shorter, slightly faster, and because it scales to literals that are bigger than what the Number type can represent accurately. Try `BigInt(77777777777777777777)` vs. `77777777777777777777n` for an example. – jmrk Apr 20 '23 at 19:33
  • @jmrk You're correct that the issue is not directly related to JavaScript's 32-bit truncation or the MAX_SAFE_INTEGER limitation. 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. – BIS Tech Apr 21 '23 at 02:11
  • Modified my answer, try again – BIS Tech Apr 21 '23 at 02:12
  • 1
    Since `3*16 < 53`, this still can't possibly work. I would humbly suggest that you consider testing your code yourself before posting it. – jmrk Apr 21 '23 at 09:20