views:

2420

answers:

5

I'm in a computer systems course and have been struggling, in part, with Two's Complement. I want to understand it but everything I read hasn't brought the picture together for me. I've read the wikipeida article and various other articles including my text book.

Hence, I wanted to start this community wiki post to define what Two's Complement is, how to use it and how it can effect numbers during operations like casts (from signed to unsigned and vice verse), bit-wise operations and bit-shift operations.

What I'm hoping for is a clear and concise definition that is easily understood by programmers who do not hold a PhDs (or even a B.S.) in Computer Science. (I have more of a software engineering B.S. and am pursuing a M.S. in Software Engineering)

+19  A: 

Two's complement is a clever way of storing integers so that common math problems are very simple to implement.

To understand, you have to think of the numbers in binary.

It basically says,

  • for zero, use all 0's.
  • for positive integers, start counting up, with a maximum of 2(number of bits - 1)-1.
  • for negative integers, do exactly the same thing, but switch the role of 0's and 1's (so instead of starting with 0000, start with 1111 - that's the "complement" part).

Let's try it with a mini-byte of 4 bits (we'll call it a nybble - 1/2 a byte).

  • 0000 - zero
  • 0001 - one
  • 0010 - two
  • 0011 - three
  • 0100 to 0111 - four to seven

That's as far as we can go in positives. 23-1 = 7.

For negatives:

  • 1111 - negative one
  • 1110 - negative two
  • 1101 - negative three
  • 1100 to 1000 - negative four to negative eight

Note that you get one extra value for negatives (1000 = -8) that you don't for positives. This is because 0000 is used for zero.

Doing this, the first bit gets the role of the "sign" bit, since it is always '1' for negative numbers, and '0' for non-negatives (zero and positive).

Does this help?

lavinio
I considered using a nibble for demonstration as well. We designed a 4-bit processor in college.
Nosredna
Yes, that does help. Thats gotta be one of the best explanations I've ever read. Thank you for taking the time to write that.
Frank V
Probably the best part of two's complement is how it simplifies math. Try adding 2 (0010) and -2 (1110) together and you get 10000. The most significant bit is overflow, so the result is actually 0000. Almost like magic, 2 + -2 = 0.
Naaff
Can I suggest using three bits instead of four for the example? That would allow you to more easily enumerate all of the values, and three bits is actually a pretty traditional chunk size (cf., the notation "\012" for C ad so on) though it started to fall out of favour in the late 1970s.
Curt Sampson
Another advantage besides easy addition and subtraction is that 2s complement only has one zero. If you were using a simple sign bit, say using 0001 to represent +1 and 1001 to represent -1, you would have two zeros: 0000 ("+0") and 1000 ("-0"). That's a real pain in the behind.
Jörg W Mittag
@lavinio: Why is there no 2's complement counterpart for floats?
Lazer
@eSKay: floats aren't stored that way. They are stored in three pieces - the mantissa (the number itself), the exponent (the scale, or "where do I put that decimal point", and the sign. There are lots of details, including special configurations to denote things like positive and negative infinity and not-a-number. And floats (4-byte, 8-byte, 10-byte, or some other rare variations) are approximations of values in many cases. See http://en.wikipedia.org/wiki/Floating_point for a good discussion of the format.
lavinio
@lavinio: I know the mastissa-exponent-sign format. What I was asking is that why can't we have a format for floating point numbers in which we do not care about the sign of the numbers while computing results... like it happens with 2's complement for integers.
Lazer
@eSKay: If two numbers had the same exponent, then the mantissas could, I suppose, be treated as two's complement numbers in some hypothetical float format. But floats are more sophisticated than just numbers with exponents. There is a difference between +inf and -inf, and even +0 and -0 - see http://en.wikipedia.org/wiki/Floating_point#Special_values - so two's complement doesn't really work here.
lavinio
+5  A: 

I wonder if it could be explained any better than the wikipedia article??

The basic problem that you are trying to solve with two's compliment representation is the problem of solving negative integers.

First consider an unsigned integer stored in 4 bits. You can have the following

0000 = 0
0001 = 1
0010 = 2
...
1111 = 15

These are unsigned because there is no indication of whether they are negative or positive.

To store negative numbers you can try a number of things. First, you can use sign magnitude notation which assigns the first bit as a sign bit to represent +/- and the remaining bits to represent the magnitude. So using 4 bits again and assuming that 1 means - and 0 means + then you have

0000 = +0
0001 = +1
0010 = +2
...
1000 = -0
1001 = -1
1111 = -7

So you see the problem there - you have positive and negative 0. The bigger problem is adding and subtracting binary numbers. The circuits to add and subtract using sign magnitude will be very complex.

What is

0010
1001 +
----
?

Another system is excess notation. You can store negative numbers, you get rid of the two zeros problem but addition and subtraction remains difficult.

So along comes twos compliment. Now you can store positive and negative integers and perform arithmetic with relative ease. there are a number of methods to convert a number into twos compliment. Hers one:

  1. convert the number to binary (ignore the sign for now) e.g 5 is 0101 and -5 is 0101

  2. if the number is a positive number then you are done. e.g. 5 is 0101 in binary using twos compliment notation.

  3. If the number is negative then

    3.1 find the compliment (invert 0's and 1's) e.g. -5 is 0101 so finding the compliment is 1010

    3.2 Add 1 to the compliment 1010 + 1 = 1011 Therefore -5 is 1011 in binary using twos compliment notation.

So what if you wanted to do 2 + (-3) in binary? 2 + (-3) is -1. What would you have to do if you were using sign magnitude to add these numbers? 0010 + 1011 = ? Using twos compliment consider how easy it would be.

 2 =  0010
 -3 = 1101 +
 and the answer is 1111

Converting 1111 to decimal we

  1. The number starts with 1 so its negative so we find the compliment = 0000
  2. Add 1 = 0001
  3. Convert to decimal = 1 4 Apply the sign = -1

Tada!

Vincent Ramdhanie
@Vincent Ramdhanie: Why is there no 2's complement counterpart for floats?
Lazer
The best you can do with floats is to approximate them using integers. Usually, floating point numbers are stored using IEEE 754 Single and double precision floating point format.
Vincent Ramdhanie
A: 

I liked lavinio's answer, but shifting bits adds some complexity. Often there's a choice of moving bits while respecting the sign bit or while not respecting the sign bit. This is the choice between treating the numbers as signed (-8 to 7 for a nibble, -128 to 127 for bytes) or full-range unsigned numbers (0 to 15 for nibbles, 0 to 255 for bytes).

Nosredna
+1  A: 

Imagine that you have a finite number of bits/trits/digits/whatever. You define 0 as all digits being 0, and count upwards naturally:

00
01
02
..

Eventually you will overflow.

98
99
00

We have two digits and can represent all numbers from 0 to 100. All those numbers are positive! Suppose we want to represent negative numbers too?

What we really have is a cycle. The number before 2 is 1. The number before 1 is 0. The number before 0 is... 99.

So, for simplicity, let's say that any number over 50 is negative. "0" through "49" represent 0 through 49. "99" is -1, "98" is -2, ... "50" is -50.

This representation is ten's complement. Computers typically use two's complement, which is the same except using bits instead of digits.

The nice thing about ten's complement is that addition just works. You do not need to do anything special to add positive and negative numbers!

Captain Segfault
A: 

two complement is find out by adding one to 1's complement of the given number . let we have to find out 2's complement of 10101 then find its 1 complement,that is, 01010 add 1 to this result,that is,01010+1=01011,which is the final answer

evaa