Binary numbers and 2's complement.

  1. Overview
  2. Binary representation
  3. Addition of binary numbers
  4. Subtraction by 2's complement
  5. Integer precision

Overview

The computer lives in a world where absolutely everything is made up of either Zero's and One's. This is not so limiting as long as there are plenty of zero's and one's to work with.

Suppose we are allowed 8-bits, that is, 8 empty boxes in a row and in each box we must place either a 0 or a 1. This is called a byte. There are 256 different ways of placing zero's and one's into the byte. Hence, we can use these different patterns to represent the numbers 0 through 255.

For arithmetic, however, we would rather represent the numbers -128 through 127.

Binary representation

In both the unsigned representation of number 0 through 255 and the signed representation of numbers -128 through 127, we would like the representation to give simple rules for doing elementary arithmetic: addition, subtraction and multiplication. If we just arbitarily assigned each pattern of bits to a number, it might be just a big mess to try to do addition.

The binary number system representation and modular arithmetic are the solution to this problem. The binary number system uses represents a number by expressing it as the sum of pure powers of two, each power used at must once. For instance,


    6 = 4 + 2 = 2^2 + 2^1,
    5 = 4 + 1 = 2^2 + 2^0,
    4 = 2^2,
    3 = 2 + 1 = 2^1 + 2^0,
    2 = 2^1,
    1 = 2^0,

We conveniently write down the decomposition by writing a 1 i places to the left if 2^i is in the sum, 0 otherwise. For emphasis, we will write _b after the number if it is in base 2. For instance:

    6 = 2^2 + 2^1 = 110_b,
    5 = 2^2 + 2^0 = 101_b,
    4 = 2^2       = 100_b,
    3 = 2^1 + 2^0 =  11_b,
    2 = 2^1       =  10_b,
    1 = 2^0       =   1_b,
    0 = 0         =   0_b.

Addition of Binary Numbers

Adding numbers in this form follows the usual algorithm for addition learned in childhood: there is a table of 1 bit additions which is memorized, and addition proceeds right to left, with carries brought to the top of the next column to the left if the 1 bit sum requires 2 bits. The table is easy:


    0 + 0 = 0,
    0 + 1 = 1,
    1 + 0 = 1,
    1 + 1 = 10_b,

Here's an example of 23 = 10111_b plus 17 = 10001_b:

    carry ->   10111
    17    ->    10001
    23    ->    10111
   ---         ------
    40         101000

Subtraction by 2's complement

Computers use a trick to represent and work with negative integers. Because the computer allocates just so many bits for an integer, when a number becomes too large to fit within that number of bits, it wraps around to zero. This is exactly like hours which go from 12 back to 1. For a byte, the wrap around goes from 255, the maximum positive value, to 0.

Hence, counting backwards can be achieved by counting forwards: subtraction can be accomplished using addition. For a byte, 256 steps forward return you to the original location, so 255 steps forward bring you to one before the original location. So adding 255 is like subtracting 1. In general, adding 256-i is like subtracting i.

Calculating from i the number 256-i is easy when done in binary:

The result is called the two's complement of the original number. You have to be carefull to complement all 8 bits, including the leading zeros. Here's an example:
      17 = 00010001_b, 
     -17 = 11101111_b.
Let's try 23 - 17 in binary, using addition and the two's complement of 17,

    carry ->  11111111
    23    ->      10111
  - 17    ->   11101111
   ---        ---------
     6        100000110

Since only 8 bits are available, the carry-out of the last bit is lost, and we end up with 110_b.

Integer precision

A single byte gives a range of 0 to 255 unsigned or -128 to 127 signed. This is a bit too small for practical work. Arithmetic is generally done not on single bytes, but on collections of bytes. The standard word is 4 bytes, giving 32 bits of integer precision. An unsigned word uses this range as 0 up to about 4 billion, a signed word uses this range as -2 billion up to 2 billion.

Half words of 16 bits and double words of 64 bits are also used. The 16 bit word is a bit inconvenient because it is possible to overflow a 16 bit word by going too positive or too negative. If you go too positive and the word is signed, you will wrap around and have a small negative.

Larger integers, using hundreds of bytes, are possible using special software. Integers of these sizes are useful for data security, where encryption and decryption are actually arithmetic computations done on very large integers.