0

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
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
Tony Gutierrez
  • 753
  • 1
  • 6
  • 16
  • Posting your C# code is not very helpful when asking about your JavaScript problem. – Unmitigated Aug 11 '20 at 23:42
  • This isn't javascript, so please [show your code](/help/how-to-ask), that shows off the actual error. And if you're including links to external sites, please only do so _in addition to_, in instead of, showing your code. – Mike 'Pomax' Kamermans Aug 11 '20 at 23:43
  • 1
    You could just put that second fiddle in a stack snippet, i think that would make things easier. – ASDFGerte Aug 11 '20 at 23:50
  • 1
    Btw for `BigInt`, `(v << BigInt(32)) >> BigInt(32);` is basically a no-op. There is no fixed size like `ulong` here, so it achieves nothing. Does it have to be a shift, or can you just use `2630423132685782527n % (1n << 32n)`? – ASDFGerte Aug 11 '20 at 23:53
  • Created a snippet, never saw that feature before! – Tony Gutierrez Aug 11 '20 at 23:54
  • @ASDFGerte That gives the correct answer. To be honest I am a little over my head on whether I need the shift or not. If you post your code as answer and elab on why the shift is not needed in JS ill mark it. – Tony Gutierrez Aug 11 '20 at 23:56
  • 1
    Well the issue is, that in c#, your `ulong` has a fixed size of 64bit. A leftshift of 32 will then move the least significant 32 bit into the most significant 32 bit, and fill with zeroes. Shifting back will fill the most significant 32 bit with zeroes then (logical shift for ulong), so the entire operation "deletes" the most significant 32 bit. However for javascript, `BigInt` has no such fixed size, so leftshifting by 32 is simply multiplying by `2**32` on a variable-bitsize structure. Shifting back, given that it's then an even number, is just reverting the operation. – ASDFGerte Aug 12 '20 at 00:03
  • @ASDFGerte thanks for the elaboration. So basically the .asUintN(32) is doing the truncating for me,and the shift isn't doing anything. – Tony Gutierrez Aug 13 '20 at 00:56

1 Answers1

1

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
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313