Negative Integers

It's important to be able to represent negative integer values as well as positive ones. We do this by taking advantage of the fact that we have a limited integer capacity in a computer. The largest possible integer in a computer word is when all the bits are ones, in our case that's 32 one bits, representing the value 232 - 1. If you add one more to that value, you should get the value 232.  That value is represented by a one bit followed by 32 zero bits, which is 33 bits long and won't fit into a word on our computer. What happens if you do the addition is that the one bit gets lost off the left end of the sum, and you are left with the 32 zero bits; in other words, you get zero. Now if you subtract one from zero, you will be back at the value represented by 32 one bits:  232 - 1. But subtracting one from zero ought to give you -1. We will, in fact, end up using  232 - 1 as our representation for -1.

Let's look at it another way. Think of a mechanical odometer from an old car; the odometer counts up to 99999 miles and then wraps around to zero. If we had a car with the odometer set on 99999 and then drove it 5 miles (thereby adding 5 to the number we already had), it would then contain the value 4. If we drove 10 miles, it would have a 9. Notice how the value 99999 is actually behaving like a -1. Furthermore, if we had the odometer set to zero and backed the car up for a mile, it would then register 99999. Again, 99999 is acting like -1. It should be obvious by now that 99998 would act like -2. You can think up lots of examples in the same vein.

Modulo Arithmetic

What we are talking about here is called "arithmetic modulo 100000" by mathematicians. The value 100000 is called the modulus. Of course the modulus could be any other positive value. If the modulus is 12, then we would have arithmetic modulo 12. I bring that up because clocks do arithmetic modulo 12, and I want to use them for the next example. Let's look at a standard clock face with one change: it has a zero where you would normally find 12. Note how the value eleven acts as a -1 just as 99999 did in the last section. Similarly, 10 is -2, 9 is -3, and we can work our way completely around the wheel back to zero (and even beyond) this way.

Not only that, but we can also work our way around the circle clockwise with ever larger positive numbers. I have started this process in the second figure above and let it run as far as 15. You can imagine letting this go on forever (winding around and around in both directions) so that we have an infinite collection of numbers at each of the twelve positions, and every integer is there somewhere. There is a mathematical relationship among all the numbers that fall at the same position: they all give the same remainder when divided by the modulus (the modulus is 12 in this case). We don't need to pursue that further because it doesn't contribute any more to our goal of representing negative integers.

Narrowing Down

If we want our integer representations to be useful, we can't have each value representing infinitely many different integers (or even two different ones). We have to decide on a unique value for each position on the clock to represent. The obvious thing is to have the same number of positive values as negative values. On a clock, that would be six of each (For reasons that come later, we will call zero positive.). So our positive values are 0, 1, 2, 3, 4, 5, and our negative values are -1, -2, -3, -4, -5, -6. Once we decide that, our clock looks like this:

Now we have accomplished our goal: every position on the face represents exactly one integer value, and zero is approximately in the center of the group of values.

Making it More Like a Computer

So far, our clock face doesn't translate well into the computer world because 12 isn't a power of 2, so let's make a clock with 16 positions around the dial. Let's look at that clock in both decimal and in binary.

The binary view is most revealing: all the positive values begin with a zero bit, and all the negative values begin with a one bit. We can use the leftmost bit as a shortcut to tell us whether the value being represented is positive or negative. This bit is generally referred to as the "sign bit". Since the value zero has a zero sign bit, we classify it as positive.

Is That Value Positive or Negative?

We can always answer that just from knowing the modulus. Remember the third clockface. In particular, we're interested in the point at the bottom where the negatives and positives meet. The extreme negative value is represented by six, which is half the modulus. The extreme positive value is one less than that, viz. five. These observations generalize as long as the modulus is even. So, if the modulus is 1000, then 0...499 represent themselves as positive values, and 999...500 represent the negative values -1...-500.

What Value Represents the Negative of This Value?

Look back at the left side of the second clockface. Notice how 11 and 1, 10 and 2, 9 and 3, all the way to 6 and 6 always add up to 12, i.e. the modulus. The same idea holds regardless of the modulus. For example, if the modulus is 1000, and we want the value to represent -200, we would use 1000 - 200 = 800.

Negating Binary Values When the Modulus is a Power of Two

This is a very special case, but it's useful to us because the modulus will be a power of two whenever we're talking about values represented in a computer. If we have a value x that we want the negative of, we just subtract x from the modulus, and there's our answer. What makes this hard is that the modulus is a one bit followed by all zeroes, so there is massive borrowing involved in doing the subtraction. Things are a lot easier if we subtract from one less than the modulus since that value is represented by a string of all one bits. The bad news is that we will get the wrong answer every time doing this. The good news is that we know that it's always off by one, and we can correct that by just adding one to the difference. Here's an example: what is the negative of 00110 (in 5 bits)? You can verify that the orange value really is the negative of the green value by adding them: the answer is zero.

modulus - 1 11111
value to negate 00110
difference 11001
difference + 1 11010

Now here's the trick: we don't have to subtract. If we subtract 1 from 1 we get 0; if we subtract 0 from 1 we get 1. In either case we get the same result by simply inverting the bit. So the shortcut method to negate a binary value is to invert all the bits and then add one to that.

Converting between Two's-Complement Binary and Sign/Magnitude Decimal

This is a bit harder because it's a double conversion: not only do you have to convert between binary and decimal; you have to convert the sign scheme as well. Note that this problem does not come up if you are dealing with positive values. We need this method only when dealing with negatives. Here is an example: what is the 2's-complement binary equivalent of -24 in 7 bits? The barrier in the top row between 24 and 1101000 is there to indicate that you can't move directly from one to the other. The correct path is from -24 down to 24 (really hard, right?), then across from 24 to 0011000 (which we did on day one of the course), then up from 0011000 to 1101000 (which we just did in the section above). BTW, 1101000 is 104 if you treat it as an unsigned integer, and 128 - 24 = 104, so this checks out. BTBTW 128 is the modulus when you have 7-bit integers.

negative -24 1101000
positive 24    0011000
decimal binary