# Bitwise Unary NOT

Tejas Kansara

Ranch Hand

Posts: 38

posted 14 years ago

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

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

Peter den Haan

author

Ranch Hand

Ranch Hand

Posts: 3252

posted 14 years ago

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

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).]

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

Posts: 38

posted 14 years ago

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.

---------------------------------------------------------------

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

Ranch Hand

Posts: 3252

posted 14 years ago

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

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

Jane Griscti

Ranch Hand

Posts: 3141

posted 14 years ago

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

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

Jane Griscti

SCJP, Co-author Mike Meyers' Java 2 Certification Passport

Tejas Kansara

Ranch Hand

Posts: 38

posted 14 years ago

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);

}

}

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

Ranch Hand

Posts: 3252

posted 14 years ago

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

- Peter

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

Posts: 38

posted 14 years ago

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.

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.

posted 14 years ago

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

HTH,

- Manish

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

Ranch Hand

Posts: 3252

posted 14 years ago

I don't think there's anything I could add to Manish' excellent explanation.

Regarding the second issue,

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

- Peter

Regarding the second issue,

This is due to a peculiarity of the Java language - when converting numbers to short or byte, it actually performs this conversion inOriginally 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;

*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

It is sorta covered in the JavaRanch Style Guide. |