2

Why do Ruby and JavaScript bitwise operators yield different results with the same operands?

For example:

256 >> -4 # => 4096 (Ruby)
256 >> -4 # => 0 (Javascript)

Any tips/pointers are appreciated.

2
  • Which is the one you expect? You could just ask for the other one. Commented Jun 25, 2013 at 3:34
  • I'm trying to port a Javascript program to a Ruby implementation, so I guess I'm looking to achieve the Javascript result in Ruby. Mainly I want to understand why they would give two different results in the first place. Commented Jun 25, 2013 at 3:37

1 Answer 1

6

For the Ruby version, it looks like 256 >> -4 is equivalent to 256 << 4, so the negative operand essentially just switches the direction of the shift.

From looking at the ECMAScript specification for the right-shift operator, in JavaScript, the operand is converted to an unsigned 32-bit integer before the shift, so the -4 becomes 4294967292. After this conversion the 5 least-significant bits are used for the shift, in other words we would end up shifting by 4294967292 & 0x1f bits (which comes out to 28). It probably shouldn't surprise you at all to see that 256 >> 28 gives 0.

For convenience, here is the text from the spec (steps 6 and 7 are most relevant to your confusion here):

The Signed Right Shift Operator ( >> )

Performs a sign-filling bitwise right shift operation on the left operand by the amount specified by the right operand.

The production ShiftExpression : ShiftExpression >> AdditiveExpression is evaluated as follows:

  1. Let lref be the result of evaluating ShiftExpression.
  2. Let lval be GetValue(lref).
  3. Let rref be the result of evaluating AdditiveExpression.
  4. Let rval be GetValue(rref).
  5. Let lnum be ToInt32(lval).
  6. Let rnum be ToUint32(rval).
  7. Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
  8. Return the result of performing a sign-extending right shift of lnum by shiftCount bits. The most significant bit is propagated. The result is a signed 32-bit integer.

As a side note, if you want to play around with this by converting a value to an unsigned 32-bit integer you can use val >>> 0 as seen in touint32.js from V8 JavaScript Engine.

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

Comments

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.