Complementary Arithmetic
Created | Updated Feb 27, 2004
This entry explains complementary arithmetic in the familiar context of decimal numbers, demonstrating that this arithmetic is not just a special technique used by binary machines. It also describes how this arithmetic is adapted for binary machines, incidently revealing why the range of binary signed numbers is unsymmetrical, and biased in favour of negative values.
Why Use Complementary Arithmetic
Addition of two single digit numbers is easy, unless the numbers are signed. In the four sums below, for which the answers are obvious, try to consider how the answer is actually obtained in each case.
(+3) + (+5) = +8
(–3) + (+5) = +2
(–3) + (–5) = –8
(+3) + (–5) = –2
The general rule which applies in every case (the rule a machine would need to follow) is quite complicated. Something along the lines
Compare the signs of the numbers. If the same, that is the sign of the result, and the magnitudes of the numbers are to be added.
Otherwise, subtraction is required. Compare the magnitudes of the two numbers, and the result sign is the sign of the larger. Swap the numbers if need be, to subtract the smaller magnitude from the larger (perhaps doing something special if they are equal).
It would be so much easier, and quicker, if the signed numbers could just simply be added. Complementary arithmetic is designed to allow exactly that.
What is Complementary Arithmetic
Complementary arithmetic uses a standard ploy: the given problem (addition) is too difficult, so adjust the problem to make it easier. In this case, the specific manoeuvre is to eliminate negative numbers.
Let's suppose that the largest magnitude we'll need to deal with is 491. Thus, we have to be able to perform two digit arithmetic, and therefore have 100 values at our disposal, which are 0 to 99. We can use these values for the 49 numbers +1 to +49, the 49 numbers –49 to –1, the number 0, and one other number. In other words, we can use the values to encode the numbers.
It would be most convenient if the results of encoding could be added using arithmetic rules which are little changed. There are actually two reasonably simple methods to encode numbers in the range –49 to +49 as two digit values.
9's Complement Arithmetic
The numbers 0 to +49 are unmodified, but the negative numbers –49 ≤ –n ≤ –1 are encoded as 99 – n, which is known as the 9's complement of n. This subtraction is very easy to do, because no borrow among digits is possible, since 9 is the largest decimal digit. In this system, all numbers are usually referred to as 9's complement values, even if they represent positive quantities, and so have not been modified by complementation.
Addition of 9's complement values is identical to the addition of ordinary decimal numbers, except for one extra step. If adding the two leftmost digits results in a carry, this is added in the rightmost digit position, a procedure known as end-around carry. Although this step is rather unfamiliar, even possibly mysterious, it is very easy to do, and cannot result in a further carry at the left.
The basic sums given above are performed again, by translating to 9's complement values, and carrying out the addition as described, using c to denote any end-around carry.
(+3) + (+5) encodes as (03) + (05) giving (08), representing +8
(–3) + (+5) encodes as (96) + (05) giving (c01) and then (02), representing +2
(–3) + (–5) encodes as (96) + (94) giving (c90) and then (91), representing –8
(+3) + (–5) encodes as (03) + (94) giving (97), representing –2
As desired, we have added signed values by direct addition, but this method has a snag. The codes 00 to 49 represent 0 to +49, and codes 50 to 98 represent –49 to –1, but what does code 99 represent?
Code 99 is unchanged by adding zero. If any other value is added, the result will exceed 100, and cause an end-around carry. This causes the result to be equal to the number added, for example 99 + 03 = c02, which becomes 03. Thus, code 99 acts rather like zero, and is the 9's complement of 00. The ingenious convention sometimes used is that 00 represents +0 and 99 represents –0, but the awkwardness of two different zeroes and the need for end-around carry are just two reasons that 9's complement arithmetic was rarely used.
The given example can be generalised, so that any required integer can be represented. Instead of using only two decimal digits, one can use as many as are required. The 9's complementing operation just involves a number with as many nines as there are digits.
10's Complement Arithemtic
The numbers 0 to +49 are unmodified, but the negative numbers –49 ≤ –n ≤ –1 are encoded as 100 – n, which is known as the 10's complement of n. This subtraction appears to require an extra digit, but this is avoidable. The value 100 – n is formed as ( 99 – n ) + 1, that is by incrementing the 9's complement of n. As noted above, the subtraction needed to form the 9's complement is easy to perform because no borrows can occur.
Addition of 10's complement values is extremely easy, and identical to normal addition. The basic sums given above are performed again, by translating to 10's complement values. This time carries at the left are simply ignored.
(+3) + (+5) encodes as (03) + (05) giving (08), representing +8
(–3) + (+5) encodes as (97) + (05) giving (02), representing +2, with carry ignored
(–3) + (–5) encodes as (97) + (95) giving (92), representing –8, with carry ignored
(+3) + (–5) encodes as (03) + (95) giving (98), representing –2
As desired, we have added signed values by direct addition. The codes 00 to 49 represent 0 to +49, and codes 51 to 99 represent –49 to –1, but what does code 50 represent?
A case can be made for code 50 to represent the number +50, by encoding the sum (+49) + (+1) = +50. An equally valid case can be made for –50, by encoding (–50) + (+1) = –49. The simple rule that a leading digit of 4 or less signifies a positive value (or zero), and a leading digit of 5 or more signifies a negative value, is a strong bias toward choosing –50. As code 50 is its own 10's complement, this value (alone) cannot sensibly be complemented, whichever choice is made2.
The 10's complement technique can be extended to as many digits as required, just as the 9's complement can. The 10's complement is found by incrementing a 9's complement of suitable length. (This is why, for two digits, it is not called a 100's complement, as the formula 100 – n might suggest.)
The advantage of using the 10's complement encoding for addition is obvious, but it makes subtraction just as easy. To subtract a number, instead add its 10's complement! Only one example of this is given. (–5) – (–3) encodes as (95) – (97), which converts to (95) + (03) giving (98), representing –2. (The 10's complement of 97 can be formed, even though +97 is not one of the numbers that can be encoded.)
Better yet, 10's complement encoding works for multiplication, if the resulting products are truncated
(+3) x (+5) encodes as (03) x (05) giving (0015), becoming (15) representing +15
(–3) x (+5) encodes as (97) x (05) giving (0485), becoming (85) representing –15
(–3) x (–5) encodes as (97) x (95) giving (9215), becoming (15) representing +15
(+3) x (–5) encodes as (03) x (95) giving (0285), becoming (85) representing –15
Double precision products3 can also be formed with a small adjustment. If an encoding represents a negative number, add the 10's complement of the other factor at the left of the four digit product, thus
(+3) x (+5) is (03) x (05) giving (0015), representing +15
(–3) x (+5) is (97) x (05) giving (0485), adding (95--) gives (9985) representing –15
(–3) x (–5) is (97) x (95) giving (9215), adding (05--) and (03--) gives (c0015) representing +15
(+3) x (–5) is (03) x (95) giving (0285), adding (97--) gives (9985) representing –15
In summary, 10's complement arithmetic works exceedingly well for addition, subtraction and multiplication, and double precision products can be obtained with only a modest extra effort. Division is difficult.
Binary Machines
Few computers today use decimal arithmetic, as binary arithmetic requires much less hardware. The complementary arithmetic methods given above for decimal values are easily adapted for this purpose.
Instead of 9's complements, 1's complements are used, because one is the largest binary digit. Instead of 10's complements, 2's complements are used, because two is one greater than one. 2's complement arithmetic is as easy (or as difficult) as the underlying binary arithmetic.
Some hardware implementations use a few tricks, which should perhaps be mentioned. Firstly, 1's complementing is very easy indeed: zero digits become one, and one digits become zero, which is just logical complementation. As in 9's complementing, no carries occur from digit to digit, which in binary means bit to bit. Each bit can be handled separately.
The incrementing needed to form a 2's complement from a 1's complement is often performed by subterfuge. In adding most bits, a carry from lower order bits must also be handled, so a bit adder really takes three bits to give a result bit and a carry bit. The carry in is not really needed for the lower order bit, but if it happens to be provided, adding a 2's complement can be achieved by adding a 1's complement and forcing a carry into the first bit.
In 10's complement arithmetic, the digits are 'big' enough to contain a sign if the leading digit of the signed repreentation is four or less. In 2's complement arithmetic, that is no longer true, and the sign occupies a whole bit. For this reason, the choice corresponding to the value assigned to code 50 in the decimal examples is invariably made one way: the sign bit is always one for negative values4.
2's complement arithmetic allows signed numbers to be handled as unsigned numbers, by an encoding trick. That's all there is to it.
This range suffices to obtain the answer 42.
2
This problem is of minor importance in practice.
3
Products with twice as many digits as given for the factors
4
Roughly corresponding to choosing -50 in decimal