Consider the two basic arithmetic operations (addition and negation, from which subtraction can be derived easily) and how they would be performed on signed integers using the four representations.
Just toggle the sign bit. Nothing simpler. If all you want to do is negate, then this is the clear winner.
Toggle all of the bits. This is a simple and fast operation. No bit depends on any other bit, and so there are no carries, "ripple", etc.
Use the twos complement operation, i.e. toggle all bits and add 1. This is a little bit slower than negating in ones complement or signed magnitude numbers, but can still be done quickly with a relatively small amount of logic in today's computers.
Use the "twos complement" operation. (Since the only difference between this representation and twos complement is that the sign bit is inverted, this makes sense.) Excess-other-numbers does not work so simply, however.
This one is the worst. If the signs are the same, add the magnitudes and use that same sign. If the signs differ, then you must determine which one has the larger magnitude. The sign is the same as that one, and the magnitude must be obtained by subtracting (not adding) the smaller one from the larger one. (This is the way you do signed arithmetic by hand, but it's not so good for digital logic.)
Examples:
-1 1001 larger (5) 101 +5 0101 smaller(1) 001 -- ---- --- +4 ???? Subtract: 100 -> add sign of larger -> 0100 +1 1001 larger (5) 101 -5 0101 smaller(1) 001 -- ---- --- -4 ???? Subtract: 100 -> add sign of larger -> 1100 +1 0001 +5 0101 -- ---- +6 0110 Add. Leave the sign alone. -1 1001 -5 1101 -- ---- -6 1110 Add. Leave the sign alone.
Either both a subtraction circuit and an addition circuit are needed, or the subtraction could be done by twos complementing and then adding, but in that case why not use twos complement in the first place??
The rule is this: Add the codes using normal binary addition, then toggle the sign bit. Examples (using Excess-8):
-1 0111 +5 1101 -- ---- +4 0100 -> toggle sign -> 1100 +1 1001 -5 0011 -- ---- -4 1100 -> toggle sign -> 0100 +1 1001 +5 1101 -- ---- +6 0110 -> toggle sign -> 1110 -1 0111 -5 0011 -- ---- -6 1010 -> toggle sign -> 0010
Only an adder is required, but there is one (small) extra step involved.
There's a tricky way to do this one: add the numbers, and then add the carry coming out of the highest bit to the result (this was called an "end-around-carry"). Examples:
-1 1110 +5 0101 -- ---- +4 (1)0011 -> 0011+1 = 0100 +1 0001 -5 1010 -- ---- -4 (0)1011 -> 1011+0 = 1011 +1 0001 +5 0101 -- ---- +6 (0)0110 -> 0110+0 = 0110 -1 1110 -5 1010 -- ---- -6 (1)1000 -> 1000+1 = 1001
Weird, isn't it? Again, only an adder is required but with an additional step that could take a long time because it is really another complete addition!
Simply add the numbers. Period. (But ignore any carry out of the highest bit.) This is why twos complement is now universally used. Examples:
-1 1111 +5 0101 -- ---- +4 (1)0100 +1 0001 -5 1011 -- ---- -4 (0)1100 +1 0001 +5 0101 -- ---- +6 (0)0110 -1 1111 -5 1011 -- ---- -6 (1)1010
Thus only a single addition is needed, with no extra steps. Also, the same operation will add both signed and unsigned numbers. There is no difference. Also, overflow is easily detected (overflow has occurred if the sign of the result is different from the signs of both operands).