Why is -1 right shift 1 = -1 in Java? - java

I came across the question "Why is -1 zero fill right shift 1=2147483647 for integers in Java?"
I understood the concept of zero fill right shift perfectly well from the above question's answer. But when I tried to find -1>>1, I am getting a totally complex answer which I felt difficult to understand.
-1 in binary form is as follows: 11111111111111111111111111111111
After flipping the bits, I got: 00000000000000000000000000000000
Upon adding 1 to it, I got: 00000000000000000000000000000001
Now shifting one position right: 00000000000000000000000000000000
After flipping the bits, I got: 11111111111111111111111111111111
Now adding 1 to it: 00000000000000000000000000000000
I don't understand how -1>>1 is -1 itself, then?

When you do a normal right-shift (i.e. using >>, also known as an arithmetic right shift, as opposed to >>>, which is a logical right shift), the number is sign extended.
How this works is as follows:
When we right-shift we get an empty spot in front of the number, like so:
11111111111111111111111111111111
?1111111111111111111111111111111(1) (right-shift it one place)
The last 1 is shifted out, and in comes the ?.
Now, how we fill in the ? is dependent on how we shift.
If we do a logical shift (i.e. >>>), we simply fill it with 0.
If we do a arithmetic shift (i.e. >>), we fill it with the first bit from the original number, i.e. the sign bit (since it's 1 if the number is negative, and 0 if not). This is called sign extension.
So, in this case, -1 >> 1 sign-extends the 1 into the ?, leaving the original -1.
Further reading:
Arithmetic shift on Wikipedia
Logical shift on Wikipedia

>> is a 'signed right shift' operator, so it will preserve the leftmost bit.
So as -1 (dec) is 0xb11111111111111111111111111111111 (bin), right shifting it using >> will preserve the 1 and the result is again 0xb11111111111111111111111111111111 (bin).
For unsigned right shift, the operator >>> can be used. It always fills up with zeroes (0). In your case, -1 >>> 1 results in 0b01111111111111111111111111111111, or 2147483647, which is the largest possible (positive) 32 bit two's complement (and equal to Integer.MAX_VALUE).

Related

And bitwise operation gets negative value

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 .

Understanding signed numbers and complements in java

I have a 3 byte signed number that I need to determine the value of in Java. I believe it is signed with one's complement but I'm not 100% sure (I haven't studied this stuff in more than 10 years and the documentation of my problem isn't super clear). I think the problem I'm having is Java does everything in two's complement. I have a specific example to show:
The original 3-byte number: 0xEE1B17
Parsed as an integer (Integer.parseInt(s, 16)) this becomes: 15604503
If I do a simple bit flip (~) of this I get (I think) a two's complement representation: -15604504
But the value I should be getting is: -1172713
What I think is happening is I'm getting the two's complement of the entire int and not just the 3 bytes of the int, but I don't know how to fix this.
What I have been able to do is convert the integer to a binary string (Integer.toBinaryString()) and then manually "flip" all of the 0s to 1s and vice-versa. When then parsing this integer (Integer.parseInt(s, 16)) I get 1172712 which is very close. In all of the other examples I need to always add 1 to the result to get the answer.
Can anyone diagnose what type of signed number encoding is being used here and if there is a solution other than manually flipping every character of a string? I feel like there must be a much more elegant way to do this.
EDIT: All of the responders have helped in different ways, but my general question was how to flip a 3-byte number and #louis-wasserman answered this and answered first so I'm marking him as the solution. Thanks to everyone for the help!
If you want to flip the low three bytes of a Java int, then you just do ^ 0x00FFFFFF.
0xFFEE1B17 is -1172713
You must only add the leading byte. FF if the highest bit of the 3-byte value is set and 00 otherwise.
A method which converts your 3-byte value to a proper intcould look like this:
if(byte3val>7FFFFF)
return byte3val| 0xFF000000;
else
return byte3val;
Negative signed numbers are defined so that a + (-a) = 0. So it means that all bits are flipped and then 1 added. See Two's complement. You can check that the condition is satisfied by this process by thinking what happens when you add a + ~a + 1.
You can recognize that a number is negative by its most significant bit. So if you need to convert a signed 3-byte number into a 4-byte number, you can do it by checking the bit and if it's set, set also the bits of the fourth byte:
if ((a & 0x800000) != 0)
a = a | 0xff000000;
You can do it also in a single expression, which will most likely perform better, because there is no branching in the computation (branching doesn't play well with pipelining in current CPUs):
a = (0xfffffe << a) >> a;
Here << and >> perform byte shifts. First we shift the number 8 bits to the right (so now it occupies the 3 "upper" bytes instead of the 3 "lower" ones), and then shift it back. The trick is that >> is so-called Arithmetic shift also known as signed shift. copies the most significant bit to all bits that are made vacant by the operation. This is exactly to keep the sign of the number. Indeed:
(0x1ffffe << 8) >> 8 -> 2097150
(0xfffffe << 8) >> 8 -> -2
Just note that java also has a unsigned right shift operator >>>. For more information, see Java Tutorial: Bitwise and Bit Shift Operators.

why the binary representationof -127>>1 is 11000000?

I know the binary representation of -127 is 10000001 (complement).
Can any body tell me why I right shift it by 1 digit, then I get 11000000 ?
(-127) = 10000001
(-127>>1) = 11000000 ???
Thanks.
If your programming language does a sign-extending right shift (as Java does), then the left-most 1 comes from extending the sign. That is, because the top bit was set in the original number it remains set in the result for each shift (so shifting by more than 1 has all 1's in the top most bits corresponding to the number of shifts done).
This is language dependent - IIRC C and C++ sign-extend on right shift for a signed value and do not for an unsigned value. Java has a special >>> operator to shift without extending (in java all numeric primitive values are signed, including the misleadingly named byte).
Right-shifting in some languages will pad with whatever is in the most significant bit (in this case 1). This is so that the sign will not change on shifting a negative number, which would turn into a positive one if this was not in place.
-127 as a WORD (2 bytes) is 1111111110000001. If you right shift this by 1 bit, and represent it as a single byte the result is 11000000 This is probably what you are seeing.
Because, if you divide -127 (two's-complement encoded as 10000001) by 2 and round down (towards -infinity, not towards zero), you get -64 (two's-complement encoded as 11000000).
Bit-wise, the reason is: when right-shifting signed values, you do sign-extension -- rather than shifting in zeroes, you duplicate the most significant bit. When working with two's-complement signed numbers, this ensures the correct result, as described above.
Assembly languages (and the machine languages they encode) typically have separate instructions for unsigned and signed right-shift operations (also called "logical shift right" vs. "arithmetic shift right"); and compiled languages typically pick the appropriate instruction when shifting unsigned and signed values, respectively.
It's sign extending, so that a negative number right shifted is still a negative number.

"<<" operator in java

Fallowing statement is from Character class of java:
(1 << Character.PARAGRAPH_SEPARATOR)) >> type
PARAGRAPH_SEPARATOR is a byte and type is an integer.
The operators in this sentence, what do they do? how and where I can use those operators?
Here is the oracles java.lang.Character doc. Nearly all the methods in the class uses those operators.
They are bit-shift operators. << shifts the bits "left" (towards the most-significant bit), and vice-versa for >>. Shifting left or right by n bits is pretty much the same as multiplying or dividing, respectively, by 2n.
See #axtavt's comment for an explanation of how these operators are being used in this context.
These are the bitwise shift operators.
If you left shift the following byte:
00000001
you would get:
00000010
I.e. the pattern has "shifted" to the left and zeros fill in on the right. So if you apply the right shift operator >> on that result, you'll get the original byte again.
You'll notice that the decimal values of these numbers are 1 and 2. If you shift left once again you'll get:
00000100 = 4
So you see that shifting to the left multiplies the number by two (given that it doesn't overflow), while right shifting divides by two. This happens very efficiently in most computers. So that's one example of how you might use these operators in a practical way.
Bitwise operators: http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
<< is the left shift operator: It shifts the binary number stored in the computer left. For example, 9 in binary is 1001. 9 << 2 makes 100100 in binary (36), because it shifts it left and adds 0s at the end. 1 << n is the same thing as Math.pow(2, n) except it is way faster and better in general, as well as returning int, not double.
>> is right shift. It shifts it right, and discards empty bits. 13 is 1101 in binary, so 13 >> 1 is 110 in binary, or 6 normally.
It works as a highly optimized multiple comparison. The signed left shift operator "<<" shifts a bit pattern to the left, and the signed right shift operator ">>" shifts a bit pattern to the right. The bit pattern is given by the left-hand operand, and the number of positions to shift by the right-hand operand. The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension.
for more detail,You can visit below link .
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

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