A Minus With No Minus Sign
How a row of switches stands for a negative number, and why that turns subtraction into ordinary addition.
Every number so far has been zero or up. Programs go down too. A score drops, a player moves left, a countdown runs out. They need negative numbers.
Here the machine has a real problem. It has no minus sign. It has switches, and a switch is only ever on or off. So how do you write −1 with nothing but bits?
The answer is called two’s complement.
Borrow a switch for the sign
The machine cannot add a minus symbol, so it gives up half its range and spends it on negatives. A signed byte runs −128 to +127 instead of 0 to 255. That is the same 256 patterns, split so half of them count below zero.
The top switch does the dividing. Off, and the number is zero or positive. On, and the number is negative. We call that top bit the sign bit.
Count backwards off the end
Here is the trick itself. What is one less than zero?
Start at 00000000 and tick down by one. You fall off the bottom and land at the top:
11111111, every switch on. So −1 is the all-ones byte. Read as a plain unsigned number,
that same pattern is 255.
The rule behind it: the pattern for −n is 256 − n. For −1 that is 255:
SHOW 256 - 1
255
The same switches carry two meanings. 11111111 is 255 read plainly and −1 read
signed. The bits do not change. The reading does.
The switches for minus five
Take −5. By the rule its pattern is 256 − 5, which is 251:
SHOW BIN 11111011
251
The top switch is on, so this is a negative. The rest spell out which negative.
Why bother? Addition just works
This looks like a strange way to write negatives, until you add one. Take 5 and add −5’s pattern, 251:
SHOW 5 + 251
256
5 + 251 comes to 256, and 256 is 1 00000000. That is a one followed by eight zeros.
A byte has room for eight. The leading 1 falls off the top and is gone, leaving
00000000, which is zero. So 5 + (−5) = 0, worked out by plain addition.
That is the point of two’s complement. The machine needs no separate subtraction. To subtract, it adds the negative, and the overflow tidies itself away. One adder does both jobs.
The seam
Splitting the range leaves a join. Count up through the positives to 127 (01111111) and
add one more. The pattern becomes 10000000, whose top switch is now on.
Read signed, that is not 128. It is −128. Push one past the biggest positive and you land on the biggest negative. A count that runs off the top reappears at the bottom, which is a bug worth knowing about before it bites.
When it’s wrong, see why
- The number is about 256 away from what you expected, like −1 showing as 255. The byte is being read unsigned when you meant it signed, or the other way round. The bits are right and the reading is not.
- A positive turned into a huge negative. You crossed the seam and wrapped around it. Check whether the value could have run off the end of its range.
- Which bit is the sign? Always the top one. Read it first. On means negative.
What you’ve learnt
- The machine writes negatives with two’s complement. In a byte the pattern for −n is
256 − n, so −1 is
11111111. - The top bit is the sign, and on means negative.
- The same switches mean a positive or a negative. The reading decides.
- The scheme exists because addition then just works, so there is no separate subtraction.
- There is a seam: counting past +127 wraps to −128.
What’s next
You can read a byte as bits, as hex, as a positive and as a negative. In the next module, Working the Bits, we stop reading the switches and start changing them.