JakeDrone
JakeDrone

Reputation: 183

Why doesn't (52 & (1 << 37)) return 0?

I'm trying to make an algorithm that given an integer, spits out the string representation of its binary form.

Now, I'm basically comparing a mask to see where to append the 1/0 bits. This worked fine until slightly larger numbers appeared, e.g.: (52 & (1 << 37)) which, if I understood the bitshift operator correctly (apparently I didn't) should return 0, because (1 << 37) = 1 and 37 * 0's. Now last time I checked, there are no 1's in the 38th place of the decimal 52 in binary format, so why does this return 32?

Upvotes: 0

Views: 100

Answers (3)

Stephen C
Stephen C

Reputation: 719596

This entire expression is performed using 32 bit numbers because all of the operands are int values.

So therefore 1 << 37 is not a "one" followed by 37 "zero" bits.

In fact, JLS 15.9 says that the shift count is masked with 0x1f (for the 32 bit shift operators). Thus 1 << 37 actually means the same thing as 1 << 5; i.e. a "one" followed by 5 "zero" bits.

If you want to use 64 bit integers in the shift expression, the first operand must be a long; i.e. (52 & (1L << 37)).

Upvotes: 6

tevemadar
tevemadar

Reputation: 13225

Because the Java Language Specification says about left-shifting (an older one, but these things do not change much) that

If the promoted type of the left-hand operand is int, then 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 (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.

So when operating on 32-bit ints, the << 37 in your code becomes << 5, and 52 & (1 << 5) is really 32.

Upvotes: 0

Thiyanesh
Thiyanesh

Reputation: 2360

In java, Integer is a 32 bit representation (irrespective of 32 or 64 bit architecture).

The following will give a 0 as expected while long is used(37 < 64):

    (52 & (1L << 37))

With long, the same problem will arise for a shift greater than 63 (more specifically greater than (1 << 63) - 1))

Now considering why the answer is 32 with integer:

   1 << 31 == Integer.MIN_VALUE
   
   (1 << 32) - 1 == 0

   1 << 32 == 1 == 2^(32 - 32) == 2^0

   1 << 33 == 2 == 2^(33 - 32) == 2^1

   1 << 34 == 4 == 2^(34 - 32) == 2^2
   
   1 << 37 == 32 == 2^(37 - 32) == 2^5

Upvotes: 1

Related Questions