views:

268

answers:

3

I'm wondering if perhaps this is a JVM bug?

java version "1.6.0_0" OpenJDK Runtime Environment (IcedTea6 1.4.1) (6b14-1.4.1-0ubuntu13) OpenJDK 64-Bit Server VM (build 14.0-b08, mixed mode)

class Tmp {
    public static void main(String[] args) {
        System.out.println("1>>1 = "+(1>>1));
        System.out.println("1>>2 = "+(1>>2));
        System.out.println("1>>31 = "+(1>>31));
        System.out.println("1>>32 = "+(1>>32));
        System.out.println("1>>33 = "+(1>>33));
    }
}

produces this when I run it:

1>>1 = 0
1>>2 = 0
1>>31 = 0
1>>32 = 1 <---------- should be 0 i think
1>>33 = 0

I also get the same results for any multiple of 32.

do I need to write my own right-shift to check for this?

A: 

Java ints are 32 bits. You're on a 64 bit machine. The bits to the left of the integer space are garbage values.

audiodude
-1 That's not how the JVM works... even though he's on a 64-bit machine, it still treats ints as 32 bits.
Vuntic
I thought being on a 64bit machine only affects the size of pointers, not data types? Can anyone confirm this?
Dave
@dave depends on the language. sadly not nice and consistent :(
Arthur Ulfeldt
Wrong. As the language in question is Java the correct. answer to Dave is 'yes'.
EJP
+11  A: 

It's not a bug. In n >> m, it only looks at the last five bits of m - so any number greater than 31 will be reduced to that number mod 32. So, (256 >> 37) == 8 is true.

Edit: This is true if you're working with ints. If it's longs, then it looks at the last six bits of m, or mods by 64.

Vuntic
So (1 >> 32) becomes (1 >> 0)? Weird.
egrunin
+1. You may want to cite JLS [§15.19](http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.19).
Matthew Flaschen
A bit sad about this. Why did Java define it this way. I thought C++ actually took extra step (CPU instructions) to take care of that. The decision seems to stem from decade-old microprocessors.
rwong
@rwong, wrong again. C++ says, "The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand." That means if you do (1 >> 33), you're opening yourself up to nasal demons. Java is being far more specific than C++, not less.
Matthew Flaschen
I thought (-9 % 9) == 4 would be strange enough in C++. (I know the reason, but it was still amusing)
rwong
@rwong: o_O how does that happen?
Vuntic
@Vuntic: int c = ((unsigned int) -9) % ((unsigned int) 9);
rwong
+15  A: 

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5121

15.19 Shift Operators

If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f. The shift distance actually used is therefore always in the range 0 to 31, inclusive.

If the promoted type of the left-hand operand is long, then only the six lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x3f. The shift distance actually used is therefore always in the range 0 to 63, inclusive.

(emphasis mine)

rwong