Reputation: 183
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
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
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 int
s, the << 37
in your code becomes << 5
, and 52 & (1 << 5)
is really 32
.
Upvotes: 0
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