55

JavaScript converts operands to 32-bit signed ints before doing bitwise operations. It also does the operation with 32-bit signed ints, meaning that the result is a 32-bit signed int.

Because I'd like to do bitwise operations with 32-bit unsigned ints, I'm wondering if there is a way to use JavaScript's mangled result to find out the intended result.

To demonstrate my idea, for example, in C, which is the reference as to what I'd like,

unsigned int a = 3774191835u;
unsigned int b = a >> 2;
/* b == 943547958 */

In JavaScript,

 var a = 3774191835;
 var b = a >> 2;
 /* b == -130193866 */

Let's try this with a different operation. In C,

unsigned int a = 1986735448u;
unsigned int b = a << 1;
/* b == 3973470896 */

In JavaScript,

 var a = 1986735448;
 var b = a << 1;
 /* b == -321496400 */

Now that JavaScript has evaluated my bitwise operation with the operand as an signed int, we of course, get a different result to what we would in C, where we can properly do bitwise operations on unsigned ints.

I know it's possible, but I'm unsure of a way that I can, essentially, turn JavaScript's result into the intended result.


Zero-fill right shift the result by zero works for the second case only, but not the first.

 var a = 3774191835;
 var b = (a >> 2) >>> 0;
 /* b == 4164773430 */

 var a = 1986735448;
 var b = (a << 1) >>> 0;
 /* b == 3973470896 */
Delan Azabani
  • 79,602
  • 28
  • 170
  • 210

3 Answers3

121

You only have to follow these rules:

  1. always end bit wise ops with >>> 0 so the result gets interpreted as unsigned.
  2. don't use >>. If the left-most bit is 1 it will try to preseve the sign and thus will introduce 1's to the left. Always use >>>.

Examples:

C:  (3774191835 >> 2) | 2147483648
js: (3774191835 >>> 2 | 2147483648) >>> 0

C:  1986735448 << 1
js: (1986735448 << 1) >>> 0

C:  3774191835 & 4294967295
js: (3774191835 & 4294967295) >>> 0

Only if the last op is >>>, >>> 0 is not necessary.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
Ernesto Badillo
  • 4,000
  • 2
  • 18
  • 6
  • 3
    +1 and this is also nicely described here: [>>> Zero-fill right shift @ MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#%3E%3E%3E_%28Zero-fill_right_shift%29) – Stano Jul 12 '13 at 17:42
  • 1
    Oh, Javascript, why must you be so odd? – Radvylf Programs Aug 14 '18 at 13:42
3

It's ugly, but:

var a = 1986735448;
var b = (a << 1) >>> 0;
/* b = 3973470896 */
Delan Azabani
  • 79,602
  • 28
  • 170
  • 210
Paul
  • 139,544
  • 27
  • 275
  • 264
  • 1
    @Delan Azabani, It's just because >>> returns an unsigned value. The shift does the same thing signed or not it's only the Javascript engines interpretation of the bit that changes. For that reason you only have to >>> 0 once after multiple bitwise operations like ((a | 2) << 1) >>> 0 – Paul Jul 23 '11 at 04:26
  • I understand that; however, `(3774191835 >> 2) >>> 0` returns `4164773430` in JavaScript, which is wrong. I'm not really sure what to do here. – Delan Azabani Jul 23 '11 at 05:21
1

JavaScript takes care of this problem by offering two bit shift operators, >> and >>>. You want >>> to do a shift without shifting the sign bit.

jswolf19
  • 2,303
  • 15
  • 16
  • No, it doesn't. JavaScript still converts operands to 32-bit signed ints, and returns the operation's result as a 32-bit signed int. Please see my updated answer, that shows that this is not related to bit shifts specifically. – Delan Azabani Jul 23 '11 at 03:57
  • When I do `alert(3774191835>>>2)`, it gives me 943547958, so I guess something's happening in the assignment? – jswolf19 Jul 23 '11 at 03:59
  • That specific case might happen to be fixed with an unsigned right shift, but what about all the other operators? – Delan Azabani Jul 23 '11 at 04:00
  • It seems @PaulPRO has an answer for that ^_^ – jswolf19 Jul 23 '11 at 04:02
  • +, -, * don't care about the signedness, the result (binary bit pattern) is the same. for divide you can use (a >>> 0) / b – Jochen Feb 10 '14 at 16:15