I am beginner to java... I have tried very much but could not find the way the following line
System.out.println (-1>>>1);
gives 2147483647 ?
Can anyone help me ?
This is because the binary representation of -1 is 11111111111111111111111111111111. When you perform an unsigned right bit-shift operation (>>>) on it it moves all of the bits right by the argument (1 in this case) and fills in empty spaces on the left with zeros so you get 01111111111111111111111111111111 which is the binary representation of Integer.MAX_VALUE = 2147483647 (not sure where you got 2147483648 from).
>>> is the bitwise right-shift operator, with 0 sign extension - in other words, all bits "incoming" from the left are filled with 0s.
-1 is represented by 32 bits which are all 1. When you shift that right by 1 bit with 0 sign extension, you end up with a value which has the 31 bottom bits still 1, but 0 for the top bit (the sign bit), so you end up with Integer.MAX_VALUE - which is 2147483647, not 2147483648 as your post states.
Or in JLS terms, from section 15.19:
The value of n >>> s is n right-shifted s bit positions with zero-extension, where:
If n is positive, then the result is the same as that of n >> s.
If n is negative and the type of the left-hand operand is int, then the result is equal to that of the expression (n >> s) + (2 << ~s).
If n is negative and the type of the left-hand operand is long, then the result is equal to that of the expression (n >> s) + (2L << ~s).
This definition ends up being a bit of a pain to work with - it's easier to just work with the "0 sign extension right-shift" explanation, IMO.
Related
I am trying to underestand the concept of shift operators,
and I was testing the following code:
15 >> 2;
- 15 >> 2
The result from the first statement is 3 as 15/4=3
but the result from the second statement is -4.
I understand that the binary of -15 is 11110001 and when we shift 2 to the right, we have 11111100, and this is -4. but I don't underestand why the result is different from the simple division which is -15/4= -3 and not -4?
please guide me why this happened?
The shift operator drops any mathematical fraction by taking the floor, not the truncation. The JLS, Section 15.19, states:
The value of n >> s is n right-shifted s bit positions with sign-extension. The resulting value is floor(n / 2s). For non-negative values of n, this is equivalent to truncating integer division, as computed by the integer division operator /, by two to the power s.
The floor of -3.75 is -4 whereas truncation would have yielded -3.
When the value is right-shifted, bits are lost as they are shifted "off the end" of the value. This is what is responsible for the floor operation.
-15: 11110001
-4: 11111100 // The rightmost 1 bit above is lost, resulting in what looks like the floor function.
Java uses two's complement to represent negative numbers.
Shifting right by n bits on a two's complement signed binary number has the effect of dividing it by 2n, but it always rounds down (towards negative infinity). This is different from the way rounding is usually done in signed integer division (which rounds towards 0).
I have this code:
int code = 0x92011202;
int a = (code & 0xF0000000) >> 28;
int b = (code & 0x0F000000) >> 24;
// ..
int n = (code & 0x0000000F);
But if most significant bit of code is equal to 1 (from 9 to F) a comes negative value. All other variables
works fine.
Why this happen?
This is explained in The Java Tutorials.
Specifically :
The unsigned right shift operator ">>>" shifts a zero into the
leftmost position, while the leftmost position after ">>" depends on
sign extension.
Java uses 2s complement variables. The only aspect about 2s complements that you care about is that, if the leftmost bit is a 1, the number is negative. The signed bitshift maintains sign, so if code is negative to begin with, it stays negative after the shift.
To fix your program use >>> instead which is a logical bitshift, ignoring sign
The most significant bit of code represents the sign -- 0 means the number is positive and 1 means the number is negative.
If you just print out code you'll find that it's negative.
Because the shift operator takes into account the sign (it's a signed shift), a will get a negative value if code is negative.
The max value of "int" is 2^31-1. 0xF0000000 is a negative number. And any number with most significant bit equals to 1 is negative .
Simple question: why if I apply unsigned right shift in Java to byte variable (and short as well) it threats it as int:
byte x = -1;
System.out.println(x >> 2);
System.out.println(x >>> 1);
System.out.println(Integer.MAX_VALUE);
Console output:
-1
2147483647
2147483647
One can only use the shift operators on ints and longs in Java (just like all other numeric operators), thus the byte is automatically cast to an int before shifting it. This also happens with the arithmetical right shift, but -1 >> 2 is -1 no matter what type -1 is, because the binary representation 111...111 shifted right arithmetically is still 111...111, while shifted logically it becomes 011...111, i.e. the maximum value of the shifted type.
PS: An arithmetic shift is a signed shift, and a logical shift is an unsigned shift.
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.
I came across an interesting scenario, When working with bitwise shift operator. If the second operand is negative, how does the bitwise shift operation works? .
i.e a << b , "<<" shifts a bit pattern to the left by b bits in a. But if b is neagtive, shouldn't it be an error at runtime ?
I am able to run the below code successfully but I don't understand how it works?
public static void bitwiseleftShift(char testChar)
{
int val=testChar-'a';
int result= 1<<val;
System.out.println("bit wise shift of 1 with val="+val+" is "+result);
}
Input
bitwiseleftShift('A');// ASCII 65
bitwiseleftShift('0'); // ASCII 48
Results
bit wise shift of 1 with val=-32 is 1
bit wise shift of 1 with val=-49 is 32768
ASCII for 'a' is 97. Can someone help me understand how this works?
But if b is neagtive, shouldn't it be an error at runtime?
Not according to the Java Language Specification, section 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.
So a shift of -32 actually ends up as a shift of 0, and a shift of -49 actually ends up as a shift of 15 - hence the results you saw.