Tony Gutierrez
Tony Gutierrez

Reputation: 771

Bitshift operation with long unsigned - Off by one issue

I have a simple bitshift operation in c# that I am porting to JS. You can see it here: https://dotnetfiddle.net/Au62NB

//C# code
ulong v = 2630423132685782527;
UInt32 v1 = (UInt32)(v >> 32);
UInt32 v0 = (UInt32)((v << 32) >> 32);
Console.WriteLine("v1:v0 " + v1 +" : " + v0); //v1:v0 612443111 : 280284671

Value v0 is always off by 1 in NodeJS (280284672). I have tried everything I could find on google, BigInt, big-integer library from npm, etc. Does anyone have an idea?

let v = BigInt('2630423132685782527');

let v1 = v >> BigInt(32)
let v0 = (v << BigInt(32)) >> BigInt(32);
v0 = Number(v0) >>> 0; //not even sure why I have to do this, something with converting signed/unsigned.

console.log("v1:v0", Number(v1), Number(v0)); //"v1:v0", 612443111, 280284672

Upvotes: 0

Views: 344

Answers (1)

Roko C. Buljan
Roko C. Buljan

Reputation: 206218

JavaScript's Number has no notion for numbers larger than 253 - 1 (2 ** 53 - 1 = 9007199254740991 AKA Number.MAX_SAFE_INTEGER).
To represent signed integers with arbitrary larger values use BigInt (not available in Safari and IE and Node prior to 10.4)

Also worth reading: BigInt/asUintN

The BigInt.asUintN static method is used to wrap a BigInt value to an unsigned integer between 0 and 2width-1.

const v = 2630423132685782527n;
const v1 = v >> 32n;
const v0 = (v << 32n) >> 32n;
const UintN_v0 = BigInt.asUintN(32, v0);

console.log(`v1:${v1} v0:${UintN_v0}`);   // v1:612443111 v0:280284671

Upvotes: 1

Related Questions