(-1 >>> 32) == -1? [duplicate] - java

This question already has answers here:
why is 1>>32 == 1?
(2 answers)
unsigned right Shift '>>>' Operator in Java [duplicate]
(1 answer)
Why is (-1 >>> 32) = -1? [duplicate]
(1 answer)
Closed 9 years ago.
Why the expression (-1 >>> 32) in Java is evaluated to -1 instead of 0 as expected? The >>>-shift-operator should fill in preceeding 0s, so the result should have all bits set to 0.
This is weird, because it breaks the semantics of >>>: e.g. (-1 >>> x) has the first x bits set to 0 for all 0 <= x <= 31. The only (unexpected) exception is 32.
Is this intentional behaviour, a bug or an (overmotivated) compiler optimization?
I used the expression ~(-1 >>> x) for expanding a cidr-netmask to its 32-bit equivalent, but as it seems, /32-masks have to be handled separately.

Check this post.
Quote from answer author Rasmus Faber
From the Java Language Specification:
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.
Long in short: due to operand range limit, -1 >>> 32 is equivalent to -1 >>> 0 which is -1.

Related

Why is 3 >> 32 equal to 3? [duplicate]

This question already has answers here:
Java right shift integer by 32 [duplicate]
(2 answers)
Is right shift undefined behavior if the count is larger than the width of the type?
(2 answers)
Closed 3 years ago.
why 3 right shift 32 is equal to 3 and not 0.
I got these results in nodeJs and Java
3 >> 31 = 0
3 >> 32 = 3
3 >> 33 = 1
3 >> 34 = 0
3 >> 35 = 0
This is part of the Java language specification. The right hand operand is wrapped so that it is always in the range 0 - bits, where bits is the number of bits of the left hand operand. Since you are shifting a 32 bit integer, the right hand operand is wrapped within 0 to 31. 32 becomes 0, 33 becomes 1 etc.
See the Java language specification for 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.

In Java, why 1L << 67 equals 8? [duplicate]

This question already has answers here:
Is java bit shifting circular?
(2 answers)
Closed 4 years ago.
As asked in the title.
I know 1L << 3 = 8, and long type is 64 bit. 67 - 64 = 3. But still why 1L << 67 has the same effect with 1L << 3? Why not something like "bit overflow" happens?
Is there any docs define this behavior? Thanks.
From https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.19
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, 67 & 0x3f = 3
The spec says that the right hand side argument in the expression 'a << b' only uses the lower X bits of b, X being the appropriate number depending on whether you're going with longs, or ints.
SOURCE: The Java Language Specification, section 15.19: https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.19

bitwise operator >>> in hashCode

I have two related questions:
the bitwise operator >>> means that we are shifting the binary number by those many places while filling 0 in the Most Significant Bit. But, then why does the following operation yields the same number: 5>>>32 yields 5 and -5>>>32 yields -5. Because if the above description is correct then both these operations would have yielded 0 as the final result.
In continuation to above, As per Effective Java book, we should use (int) (f ^ (f >>> 32)) (in case the field is long) while calculating the hash code (if the field is long). Why do we do that and what's the explanation
5 can be represented as 0101 if you shift it by 1 bit i.e 5>>>1 this will result as 0010=2
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.
When you shift an integer with the << or >> operator and the shift
distance is greater than or equal to 32, you take the shift distance
mod 32 (in other words, you mask off all but the low order 5 bits of
the shift distance). This can be very counterintuitive. For example (i> >> 32) == i, for every integer i. You might expect it to shift the entire number off to the right, returning 0 for positive inputs and -1
for negative inputs, but it doesn't; it simply returns i, because (i
<< (32 & 0x1f)) == (i << 0) == i.
Answer to your first question is here why is 1>>32 == 1?
The second question answer, in short, is that in such way the whole long value is used(not a part of it) and note that it is probably the fastest way to do this.
I know this question has been answered long back, but I tried an example to get more clarification and I guess it'll others too.
long x = 3231147483648l;
System.out.println(Long.toBinaryString(x));
System.out.println(Long.toBinaryString(x >>> 32));
System.out.println(Long.toBinaryString(x ^ (x >>> 32)));
System.out.println(Long.toBinaryString((int) x ^ (x >>> 32)));
This prints -
101111000001001111011001011110001000000000
1011110000
101111000001001111011001011110000011110000
1001111011001011110000011110000
As #avrilfanomar mentions, this XORs first 32 bits of long with the other 32 bits and unsigned right shift operator helps us in doing this. Since we want to use this long field while calculating the hashcode, directly casting the long to int would mean that long fields differing only in the upper 32 bits will contribute the same value to the hashcode. This potentially means that two objects differing only in this field will have same hashcode and it'll be stored in the same bucket (with say a list to resolve collision) and this impacts the performance of hash-based collections. Hence, this operation.

unsigned right Shift '>>>' Operator in Java [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Why is (-1 >>> 32) = -1?
The unsigned right shift operator inserts a 0 in the leftmost. So when I do
System.out.println(Integer.toBinaryString(-1>>>30))
output
11
Hence, it is inserting 0 in the left most bit.
System.out.println(Integer.toBinaryString(-1>>>32))
output
11111111111111111111111111111111
Shouldn't it be 0?
See http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.19
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.
that is -1 >>> 32 is equivalent to -1 >>> 0 and -1 >>> 33 is equivalent to -1 >>> 1
and, especially confusing, -1 >>> -1 is equivalent to -1 >>> 31

Difference between >>> and >> operators [duplicate]

This question already has answers here:
Difference between >>> and >>
(9 answers)
Closed 5 years ago.
If the shifted number is positive >>> and >> work the same.
If the shifted number is negative >>> fills the most significant bits with 1s whereas >> operation shifts filling the MSBs with 0.
Is my understanding correct?
If the negative numbers are stored with the MSB set to 1 and not the 2s complement way that Java uses the the operators would behave entirely differently, correct?
The way negative numbers are represented is called 2's complement. To demonstrate how this works, take -12 as an example. 12, in binary, is 00001100 (assume integers are 8 bits though in reality they are much bigger). Take the 2's complement by simply inverting every bit, and you get 11110011. Then, simply add 1 to get 11110100. Notice that if you apply the same steps again, you get positive 12 back.
The >>> shifts in zero no matter what, so 12 >>> 1 should give you 00000110, which is 6, and (-12) >>> 1 should give you 01111010, which is 122. If you actually try this in Java, you'll get a much bigger number since Java ints are actually much bigger than 8 bits.
The >> shifts in a bit identical to the highest bit, so that positive numbers stay positive and negative numbers stay negative. 12 >> 1 is 00000110 (still 6) and (-12) >> 1 would be 11111010 which is negative 6.
Definition of the >>> operator in the Java Language Specification:
The value of n>>>s is n right-shifted s bit positions with zero-extension. If n is positive, then the result is the same as that of n>>s; if n is negative, the result is equal to that of the expression (n>>s)+(2<<~s) if the type of the left-hand operand is int, and to the result of the expression (n>>s)+(2L<<~s) if the type of the left-hand operand is long.
Just the opposite, the >>> fills with zeros while >> fills with ones if the h.o bit is 1.

Categories

Resources