2

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!

1
  • it is indeed used for rounding values but it's very dangerous as you found out. Bitwise arithmetic in JavaScript forcefully converts numeric values to 32 bits which, in turn, causes overflow problems for large numbers. Commented Oct 28, 2016 at 16:14

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for your time T.J.!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.