why is 1>>32 == 1?
Asked Answered
C

2

31

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?

Castroprauxel answered 3/7, 2010 at 5:24 Comment(5)
bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/601266 Please keep us (on SO) updated.Dallis
re @Arthur: seems like yes, you will need to write your own right-shift to check for this.Dallis
rwong: thats my bug, i will delete it. this is not a compiler bug though I still think its "wrong math".Castroprauxel
See also What's the reason high-level languages like C#/Java mask the bit shift count operand?Sloganeer
+1 Thanks for the question, never knew this. :)Anchoress
D
33

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.22.1

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)

Dallis answered 3/7, 2010 at 5:34 Comment(0)
P
20

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.

Piggyback answered 3/7, 2010 at 5:27 Comment(7)
So (1 >> 32) becomes (1 >> 0)? Weird.Thant
+1. You may want to cite JLS §15.19.Sloganeer
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.Dallis
@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.Sloganeer
I thought (-9 % 9) == 4 would be strange enough in C++. (I know the reason, but it was still amusing)Dallis
@Vuntic: int c = ((unsigned int) -9) % ((unsigned int) 9);Dallis
@Dallis (-9 % 9) is 0. Both mathematically and in C++Orvas

© 2022 - 2024 — McMap. All rights reserved.