Martin Gemme
Martin Gemme

Reputation: 345

How to do decimal Bitwise Operation in C# from Javascript's Code

I'm translating a library from javascript to C#, and felt under this case:

// Javascript
var number = 3144134277.518717 | 0;
console.log(number); // -> -1150833019

From what I read on other post, it might of been used to round values, but in this case the value isn't what I expect it to be (if it was to be rounded) and I can't reproduce in C# the same behavior with:

// C#
3144134277.5187168 | 0 // -> Operator '|' cannot be applied to operands 
                       //    of type 'double' and 'int'
// or
Convert.ToInt64(3144134277.5187168) | 0 // -> 3144134278

Thanks for any help!

Upvotes: 2

Views: 375

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075139

The way | works in javaScript is detailed in the spec, but primarily what you're seeing is that | implicitly converts its operands to 32-bit ints before doing the bitwise OR (which is a no-op because the second arg is 0). So really what you're seeing is the result of the ToInt32 operation:

  1. Let number be ? ToNumber(argument). (You can largely ignore this bit.)
  2. If number is NaN, +0, -0, +∞, or -∞, return +0.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
  4. Let int32bit be int modulo 2^32.
  5. If int32bit ≥ 2^31, return int32bit - 2^32; otherwise return int32bit.

So in C#, I think that's roughly:

double value = 3144134277.5187168;
bool negative = value < 0;
long n = Convert.ToInt64(Math.Floor(Math.Abs(value)));
n = n % 4294967296;
n = n > 2147483648 ? n - 4294967296 : n;
int i = (int)n;
i = negative ? -i : i;
Console.WriteLine(i); // -1150833019

...written verbosely for clarity. Note that the sign isn't added back to the result in quite the same place as the spec; when I did that, it didn't work correctly, which probably has to do with differing definitions between the spec's "modulo" and C#'s % operator.

And just double-checking, those steps with -3144134277.5187168 give you 1150833019, which is as it's supposed to be as well.

Upvotes: 7

Related Questions