Could anyone please explain me the following : How come the output of ~3 is -4 Could you give me a brief explaination regarding the same. And few hints related to Left/Right Shift,etc I am preparing for SCJP and in ref. books I am not having enough of explaination. Thanking you in ANTICIPATION. Regards Tejas

I think the Java 2 Certification Passport has an excellent explanation of the subject, if you can wait for its publishing date. But then again, I'm not impartial: half the 'ranch crowd has contributed to this book, and I did the technical review. To understand these operations, you need to understand binary: 0101 = (0 * 2^3) + 1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 5 Negative numbers use 2's complement: you flip all the bits (a not operation), then add one. -5 = -( 0101 ) = 1010 + 1 = 1011 Why this weird convention? Simple: this way, a number added to its negation works out to be zero using the normal bitwise addition rules: 0101 1011 ----+ 0000 Of course, that is exactly what a negative number is supposed to do. So apparently 2's complement is the right representation for a negative number under bitwise addition. (I'll leave it up to the reader to show the same for multiplication, and to see what happens if you do the same for the 8-bit representation of -5 instead of the 4-bit one shown above). Now you can understand why ~n = -n-1 for all n! It's the way negative numbers are constructed in 2's complement. Bitshifts are easy. 0101 >> 1 = 0010 = 2 = 5/2 (you lose the least significant bit) 0010 << 1 = 0100 = 4 = 2*2<br /> But watch out!<br /> 1011 >> 1 = 1101 = -3 = (-5)/2 (always rounding down, and a "1" is shifted into the left to preserve sign) 1011 >>>1 = 0101 = 5 (the unsigned bitshift operator always shifts in "0" and does not preserve sign) 0101 << 1 = 1010 = -6 (the left shift operator overflows in this case - there is no signed 4-bit representation of 5*2=10) - Peter

[This message has been edited by Peter den Haan (edited October 20, 2001).]

Tejas Kansara
Ranch Hand

Joined: Dec 14, 2000
Posts: 38

posted

0

Thanx Peter but still doubts : --------------------------------------------------------------- 0101 >> 1 = 0010 = 2 = 5/2 0010 << 1 = 0100 = 4 = 2*2<br /> What does 5/2 and 2*2 suggests ??? - Explain pleazeee ...<br /> A N D..... the one below : <br /> 1011 >> 1 = 1101 = -3 = (-5)/2 (always rounding down, and a "1" is shifted into the left to preserve sign) 1011 >>>1 = 0101 = 5 (the unsigned bitshift operator always shifts in "0" and does not preserve sign) 0101 << 1 = 1010 = -6 (the left shift operator overflows in this case - there is no signed 4-bit representation of 5*2=10)<br /> I AM CONFUSED WITH THE NEGATIVE SHIFTS <br /> i.e <br /> 1011 >> 1 is how come -3 .... 1011 >>> 1 is how come 5 .... DO ME A FAVOR AND CLEAR MY DOUBTS THANX AGAIN.

Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252

posted

0

0101 >> 1 = 0010 = 2 = 5/2 0101 = 5. 0010 = 2. Right shift by one is equivalent to integer division by 2. 0010 << 1 = 0100 = 4 = 2*2<br /> 0010 = 2. 0100 = 4. Left shift by one is equivalent to multiplication by 2.<br /> The >>> unsigned right shift operator always shifts in zeroes from the left, which means that negative numbers are turned into positive numbers - the leftmost (most significant) bit is the sign bit, always 1 for negative numbers. Just work out a few examples and you'll see the logic. The >> signed right shift operator is equivalent to integer division, for negative numbers as well as positive numbers, so right-shifting -5 gives (-5)/2 = -3. I know this feels inadequate, but at this stage nothing beats taking pencil and paper and trying things out. If you have any specific problems please post. - Peter

Hi Tejas, There are some notes and alternate links on the different number systems and two's-complement arithmetic here. They are not as succint as Peter's explanation but they may help. Peter, thanks for the book plug ------------------ Jane Griscti Sun Certified Programmer for the Javaï¿½ 2 Platform

Peter thanks for all your co-operation and help actually I have been working on bitwise topic since few days. Actually to some extent I am clear with few operators but when it comes to negative values, I get confused. Also explain how to judge a negative value when it is written in binary form. My main problem is with NEGATIVE VALUES AND SHIFTS. Mainly negative shifts. Guide me pleazzzzz. Just see to the following program and explain the output b'coz it gives a vast difference when it is 5 and -5 class RightShift { public static void main(String[] args) { int i =-5; //int i = 5; i >>= 1;

System.out.println(i); } }

Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252

posted

0

To get the decimal value of a negative binary value: just invert the 2-s complement procedure! Subtract one (using normal binary subtraction), invert all the bits, then determine the value as usual. Negative shifts. In terms of values, they are extremely easy to understand: a negative shift by 1 means the value gets divided by 2 and rounded down. In terms of bit patterns, it isn't very difficult either: the whole pattern gets shifted to the right, leftmost (sign) bit determines the value of the new bit shifted in from the left. The difficult part is probably to understand that these two viewpoints are equivalent. I can post an algebraic proof, if you want; but would that be useful to you? (The core of the proof is the observation that the unary NOT and the signed bitshift operators commute, i.e. (~n) >> 1 = ~(n >> 1)). - Peter

Tejas Kansara
Ranch Hand

Joined: Dec 14, 2000
Posts: 38

posted

0

Peter could you please explain the following : int i =-31; How will you convert the -31 to binary and back again to decimal. Please do me a favor. I am just CONFUSED with negative values. One more interesting topic double a,b; Thanx..... a = 2.0; b = 0.0; double c = a/b; Now when I do the following why it gives different results. int x = (int) c; and byte y = (byte) c; Waiting for reply.

Originally posted by Tejas Kansara: Please do me a favor. I am just CONFUSED with negative values.

Have a look at this, and see if it is of any help. HTH, - Manish

Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252

posted

0

I don't think there's anything I could add to Manish' excellent explanation. Regarding the second issue,

Originally posted by Tejas Kansara: double a,b; a = 2.0; b = 0.0; double c = a/b; Now when I do the following why it gives different results. int x = (int) c; and byte y = (byte) c;

This is due to a peculiarity of the Java language - when converting numbers to short or byte, it actually performs this conversion in two steps, first converting to an int and then casting this to a short or byte. The last step merely throws away the extraneous bits. First, the value of c is Double.POSITIVE_INFINITY (after all, you're dividing by zero). There is no direct representation of this "number" as an integer, so in "(int) c" it is converted to its closest equivalent, Integer.MAX_VALUE, the largest value a variable of type int will hold. This (2147483647) is the value you get when you print x. The expression "(byte) c" does not directly convert c to a byte; instead, it first converts c to an int, then casts the int to a byte. You could just as well replace it by "(byte) x". The bit pattern of Integer.MAX_VALUE is 01111111111111111111111111111111. Chop off the first 24 bits to give an 8-bit byte and you end up with 11111111, which works out to be -1. That is the value printed when you print y. - Peter