Bitwise or in Ruby VS JavaScript

Bitwise OR in ruby vs javascript

If you want to represent numbers with > 32 bits and perform bitwise operations on them in Javascript, you're better off using an emulated long such as this: http://closure-library.googlecode.com/svn/docs/class_goog_math_Long.html.

Take a look at this entry. Technically Javascript can represent 2^53 ints, but bitwise ops are limited to 32 bits.

What is JavaScript's highest integer value that a Number can go to without losing precision?

To elaborate, what's happening in JS when you do 89190868196442450 | 0 is Javascript is taking the least significant 32 bits and ORing them with 0, which yields 1074708816, and in Ruby it is ORing it with all of the bits. If for some reason you wanted to reproduce that in Ruby, you would AND your number with 1FFFFFFFF so you're only operating on the least significant 32 bits and then OR it by 0 (which does nothing but would give you the same result).

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

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.

Getting the same result from Ruby as Javascript for bitwise XOR

Those two are the same result, modulo 232. In Ruby you could & 4294967295 to make the result the same as in Javascript.

To cover all the cases, you need to take into account that Javascript considers binary values to be signed 32-bit integers. Ruby on the other hand will produce unsigned 32-bit integers from the & 4294967295 operation.

So, in Javascript simply:

c = a ^ b

To get the same thing in Ruby:

c = (a ^ b) & 4294967295
c -= 4294967296 if c > 2147483647

How to truncate large integers during bitwise operations to mimic JavaScript in Ruby?

This is a great question. I did some experimentation trying to figure out exactly what operations JavaScript is doing, but then I thought, "I bet the spec says." Sure enough, it did!

First I checked out the Bitwise Shift Operators section, and what I learned from that is what you already knew: Before doing bitwise operations, JavaScript converts its operands to 32-bit integers. For that, it links to the definition of an "abstract operation" (i.e. an algorithm to be implemented by JavaScript engines) called ToInt32. Happily, it's really easy to follow:

ToInt32: (Signed 32 Bit Integer)


The abstract operation ToInt32 converts its argument to one of 232 integer values in the range -231 through 231−1, inclusive. This abstract operation functions as follows:

  1. Let number be the result of calling ToNumber on the input argument. [This just converts non-numeric values like booleans and strings into numbers.]
  2. If number is NaN, +0, −0, +∞, or −∞, return +0.
  3. Let posInt be sign(number) * floor(abs(number)). [sign returns -1 if number is negative or 1 if it's positive.]
  4. Let int32bit be posInt modulo 232; that is, a finite integer value k of Number type with positive sign and less than 232 in magnitude such that the mathematical difference of posInt and k is mathematically an integer multiple of 232.
  5. If int32bit is greater than or equal to 231, return int32bit − 232, otherwise return int32bit.

We can translate this directly into Ruby (I've numbered the steps 1–5 as comments):

def to_int32(number)
# (1)(2)
begin
sign = number < 0 ? -1 : 1
abs = number.abs
return 0 if abs == 0 || abs == Float::INFINITY
rescue
return 0
end

pos_int = sign * abs.floor # (3)
int_32bit = pos_int % 2**32 # (4)

# (5)
return int_32bit - 2**32 if int_32bit >= 2**31
int_32bit
end

So, does it work?

a = 144419633058839130000
puts to_int32(a)
# => 1482551184

b = 3903086624
puts to_int32(b)
# => -391880672

Seems legit!

Now, I'm sure there are more concise and probably faster ways to do this, but this should get you started.

Bitwise NOT in ruby

I believe the same expression in Ruby would be (n/m + 0.5).to_i * m, or, alternatively, Integer(n/m + 0.5) * m.

It looks like the doubled bitwise complement there is really being used to truncate the decimal part of the calculation, in order to compute the nearest n such that n is a multiple of m. (In another language, I would say "convert to integer", but Javascript has a unified arithmetic type.)

Update: Mladen Jablanović suggests a cast, and yes, if both m and n are Fixnum, it's needed. In Ruby 1 / 3 is 0 but in JS it's 0.333... Here is a refined suggestion:

(n.to_f / m).round * m

Bitwise NOT in ruby

I believe the same expression in Ruby would be (n/m + 0.5).to_i * m, or, alternatively, Integer(n/m + 0.5) * m.

It looks like the doubled bitwise complement there is really being used to truncate the decimal part of the calculation, in order to compute the nearest n such that n is a multiple of m. (In another language, I would say "convert to integer", but Javascript has a unified arithmetic type.)

Update: Mladen Jablanović suggests a cast, and yes, if both m and n are Fixnum, it's needed. In Ruby 1 / 3 is 0 but in JS it's 0.333... Here is a refined suggestion:

(n.to_f / m).round * m

Replicating Javascript bitwise operation in Python

How about converting from uint32 to int32.

import struct
print struct.unpack('i', struct.pack('I', 0xA867Df55))[0]

OUTPUT

-1469587627

Or as @Ashwini suggests:

import ctypes
print ctypes.c_int(0xA867DF55 ^ 0).value

OUTPUT

-1469587627

Ruby Logical Operators - Elements in one but not both arrays

Arrays in Ruby very conveniently overload some math and bitwise operators.

Elements that are in a, but not in b

 a - b # [3]

Elements that are both in a and b

 a & b # [1, 2]

Elements that are in a or b

 a | b # [1, 2, 3]

Sum of arrays (concatenation)

 a + b # [1, 2, 3, 1, 2]

You get the idea.



Related Topics



Leave a reply



Submit