问题
Im sure this is an easy one for whoever sees it first!
Why in Java does code like
long one = 1 << 0;
long thirty = 1 << 30;
long thirtyOne = 1 << 31;
long thirtyTwo = 1 << 32;
System.out.println(one+" = "+Long.toBinaryString(1 << 0));
System.out.println(thirty+" = "+Long.toBinaryString(1 << 30));
System.out.println(thirtyOne+" = "+Long.toBinaryString(1 << 31));
System.out.println(thirtyTwo+" = "+Long.toBinaryString(1 << 32));
1 = 1
1073741824 = 1000000000000000000000000000000
-2147483648 = 1111111111111111111111111111111110000000000000000000000000000000
1 = 1
This does not make sense to me. long
is a 64 bit number - whereas it seems to act like an int
in the above. I know bitshifted byte
s undergo int promotion but I dont see whats going on in this case.
Any pointers on whats going on here would be good :)
Thx
EDIT: thanks for all the answers - i realised what was going on as soon as I clicked 'submit' but SO went into readonly
mode and I couldnt delete! Many thanks!
回答1:
It's because 1 is an int
literal, so <<
is applied to an integer. The result is cast to a long
, but by then it's too late.
If you write 1L << 32, etc., then all will be well. L
is used to denote a long
literal.
回答2:
First of all:
Java Language Specification paragraph 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 (0b11111). 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 (0b111111). The shift distance actually used is therefore always in the range 0 to 63, inclusive.
So, why does it work as if you are shifting int
s instead of long
s? Because you are shifting int
s! Try using a long
literal instead:
long thirtyTwo = 1L << 32;
回答3:
Well you're using int literals, which behave like ints. Use a long literal (i.e. 1L
) instead:
System.out.println(1 << 31);
System.out.println(1L << 31); // <--
-2147483648 2147483648
When you have an expression like 1 << 31
, it evaluates to a fixed value irrespective of what it's being assigned to, be it int
or long
.
回答4:
It acts like an int
because you are shifting ints ! To shift a long, you must suffix all your number with l
.
long one = 1l << 0;
long thirty = 1l << 30;
long thirtyOne = 1l << 31;
long thirtyTwo = 1l << 32;
System.out.println(one+" = "+Long.toBinaryString(1l << 0));
System.out.println(thirty+" = "+Long.toBinaryString(1l << 30));
System.out.println(thirtyOne+" = "+Long.toBinaryString(1l << 31));
System.out.println(thirtyTwo+" = "+Long.toBinaryString(1l << 32));
Which gives the following result :
1 = 1
1073741824 = 1000000000000000000000000000000
2147483648 = 10000000000000000000000000000000
4294967296 = 100000000000000000000000000000000
回答5:
This is because the number 1
in the line long thirtyTwo = 1 << 32;
is an int
by default. You need to explicit mark it as a long before you do the shift operation. What happens now is that you do a shift on an int
which then after the shift is done is casted from an int
to a long
.
long one = 1l << 0;
long thirty = 1l << 30;
long thirtyOne = 1l << 31;
long thirtyTwo = 1l << 32;
回答6:
The problem is that 1
is an integer. It will be converted to a long after the shift. Try
long one = 1l << 0;
long thirty = 1l << 30;
long thirtyOne = 1l << 31;
long thirtyTwo = 1l << 32;
回答7:
literal 1 is an int. Use 1L (L as long) and retry.
来源:https://stackoverflow.com/questions/22330107/bitshifting-a-long-in-java