I am converting some Java code to Javascript to run on node.js, and I ran into something peculiar with bit shifting.
The original Java used a long and logical bit shifting, so I’ve replicated that in Javascript (I get the same results with an arithmetic shift):
var num = 3382;
num >>> 0 & 0xFF; // 54, as expected
num >>> 8 & 0xFF; // 13, as expected
num >>> 16 & 0xFF; // 0, as expected
num >>> 24 & 0xFF; // 0, as expected
num >>> 32 & 0xFF; // 54??
num >>> 40 & 0xFF; // 13??
I get the same results on node, FF 4 and Chrome 12.
It seems that Javascript is wrapping the bits in the integer when it runs out of bits. Javascript, AFAIK, allows up to 32-bit numbers in the background, but this shouldn’t be an issue.
Binary Representation
This is what I think is happening:
0-shift: 00000000000000000000110100110110
8-shift: 00110110000000000000000000001101
16-shift: 00001101001101100000000000000000
24-shift: 00000000000011010011011000000000
32-shift: 00000000000000000000110100110110
Sanity Check
I wrote a little test in C to make sure I wasn’t going insane (note, there are compile warnings, but that’s expected):
#include <stdio.h>
int main() {
printf("Bit shift tests:\n");
printf("3382 >> 0 & 0xFF: %d\n", 3382 >> 0 & 0xFF);
printf("3382 >> 8 & 0xFF: %d\n", 3382 >> 8 & 0xFF);
printf("3382 >> 16 & 0xFF: %d\n", 3382 >> 16 & 0xFF);
printf("3382 >> 24 & 0xFF: %d\n", 3382 >> 24 & 0xFF);
printf("3382 >> 32 & 0xFF: %d\n", 3382 >> 32 & 0xFF);
printf("3382 >> 48 & 0xFF: %d\n", 3382 >> 48 & 0xFF);
printf("3382 >> 56 & 0xFF: %d\n", 3382 >> 56 & 0xFF);
printf("3382 >> 64 & 0xFF: %d\n", 3382 >> 64 & 0xFF);
}
Note
I only care about 32-bit numbers. The Java code used 64 bit numbers, but the numbers represent file sizes and I won’t be using big files (all under 50 megs or so).
Question
I have read the wikipedia articles about arithmetic and logical bit shifts, but it doesn’t seem that Javascript is following the rules.
Could someone explain to me what’s going on?
From http://ecma262-5.com/ELS5_HTML.htm
Note step 7, the shift count is truncated to 5 bits, so 32 becomes 0 and 40 becomes 8 and the values you are getting conform to the specification.