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've read hasn't brought the picture together for me. I've read the wikipedia 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 affect numbers during operations like casts (from signed to unsigned and vice versa), bit-wise operations and bit-shift operations.
What I'm hoping for is a clear and concise definition that is easily understood by a programmer.
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,
Let's try it with a mini-byte of 4 bits (we'll call it a nibble - 1/2 a byte).
0000
- zero0001
- one0010
- two0011
- three0100
to 0111
- four to sevenThat's as far as we can go in positives. 23-1 = 7.
For negatives:
1111
- negative one1110
- negative two1101
- negative three1100
to 1000
- negative four to negative eightNote that you get one extra value for negatives (1000
= -8) that you don't for positives. This is because 0000
is used for zero. This can be considered as Number Line of computers.
Distinguishing between positive and negative numbers
Doing this, the first bit gets the role of the "sign" bit, as it can be used to distinguish between nonnegative and negative decimal values. If the most significant bit is 1
, then the binary can be said to be negative, where as if the most significant bit (the leftmost) is 0
, you can say the decimal value is nonnegative.
"Sign-magnitude" negative numbers just have the sign bit flipped of their positive counterparts, but this approach has to deal with interpreting 1000
(one 1
followed by all 0
s) as "negative zero" which is confusing.
"Ones' complement" negative numbers are just the bit-complement of their positive counterparts, which also leads to a confusing "negative zero" with 1111
(all ones).
You will likely not have to deal with Ones' Complement or Sign-Magnitude integer representations unless you are working very close to the hardware.