Back Home Up Next

Numbers Fractions Negative numbers Floating point Binary arithmetic Codes

Negative Numbers

 

The integer and fractional numbers we have encountered so far have been unsigned; that is, technically they are neither positive nor negative. An 8-bit unsigned binary number such as 01001010 has the decimal value 74, and may be regarded as positive if it, say, represents the value of a check credited to a bank account; or negative if it represents a check drawn on an account.

 

We can encode binary numbers in a way that takes into account both positive and negative values. What do we know about binary numbers? We know that an n-bit number can have 2n different values, and that an n-bit unsigned integer can represent values in the range 0 to 2n - 1. There is nothing to prevent us taking these 2n different values and labeling them in any way we wish. Consider table 1.3 in which the 16 bit patterns represented by a 4-bit binary number are labeled in various ways.

 

Binary pattern

Unsigned number

System A

System B

System C

System D

System E

 

 

 

 

 

 

 

0000

0

7

-7

0

0

0

0001

1

4

-6

1

1

1

0010

2

-6

-5

2

2

2

0011

3

2

-4

3

3

3

0100

4

-8

-3

4

4

4

0101

5

12

-2

5

5

5

0110

6

-12

-1

6

6

6

0111

7

15

0

7

7

7

1000

8

4

1

-0

-7

-8

1001

9

8

2

-1

-6

-7

1010

10

9

3

-2

-5

-6

1011

11

3

4

-3

-4

-5

1100

12

-5

5

-4

-3

-4

1101

13

-7

6

-5

-2

-3

1110

14

3

7

-6

-1

-2

1111

15

42

8

-7

-0

-1

 Six ways of labeling the 16 values of a 4-bit binary number

 

The first two columns of table 1.3 provide the 16 possible values of a 4-bit binary number and its interpretation, in decimal form, as an unsigned 8421-weighted binary integer. Columns A to E describe alternative ways of renumbering these 16 binary values. In column A, we have numbered the binary values in an arbitrary fashion. There’s no reason why we can’t do this—if we want both the bit patterns 1011 and 1110 to represent 3, we can do it. Perhaps in one hundred years time a physicist will find this book in a antique bookstore and find that the coding of system A turned out to be of vital importance in quantum mechanics.... We have invented system A to demonstrate that programmers can assign any values they want to bit patterns. This point can’t be emphasized strongly enough—a pattern of bits has no intrinsic meaning, it represents whatever the programmer wants it to represent.

 

If system A has been provided to demonstrate that you can label bit patterns in any way you desire, systems B to E represent actual systems used to represent negative numbers. System B is called excess 7 because it is derived from the natural 8421 binary sequence by subtracting 7 from each unsigned value; for example the code 0101 represents 5 as an unsigned integer or 5 - 7 = -2 as an excess 7 code.   This type of code is used in floating point system arithmetic to handle negative exponents (we discuss floating point arithmetic later).

 

System C is called the sign and magnitude representation because the most-significant bit is used as a sign bit—if the sign bit is zero, the number is positive and it the sign bit is 1, the number is negative. For example, the 8-bit sign and magnitude number 001100112 is +5110, and 101100112 is -5110. Sign and magnitude numbers are not normally used by computers to represent integer values—however, the sign and magnitude system is used in floating point arithmetic to represent the mantissa.

 

Systems D and E are very similar and are called the one’s complement and the two’s complement representation of signed numbers, respectively. The positive numbers from 0 to 7 are represented in systems D and E in exactly the same way as the corresponding natural 8421 weighted binary integers. In system D, negative numbers in the range -0 to -7 are represented by inverting the bits of the corresponding positive binary number. For example, if +510 is represented by 000001012 in 8 bits, -5 is represented by 111110102. Note that the one’s complement representation of signed numbers has two zeros: +0 is 000...0 and -0 is 100...0.

 

In system E a negative number is generated by inverting the bits of the corresponding positive number and adding 1; that is, the 2’s complement of a negative number is obtained by adding 1 to the corresponding 1’s complement. For example, in eight bits the 1’s complement of -5 (system D) is obtained by taking the code for 5 (i.e., 00000101) and inverting the bits to get 11111010. The 2’s complement of -5 (system E) is obtained by adding 1 to the 1’s complement of 5 to get 11111010 + 1 = 11111011.

 

The sign and magnitude, one’s complement and two’s complement representations of signed numbers all have one feature in common. In each system the most-significant bit is 0 if the number is positive and 1 if it is negative.

 

Two’s Complement Arithmetic

 

All microprocessors use the 2’s complement system to represent signed integers. Why? What’s so special about the 2’s complement system? The answer is simple; the 2’s complement system allows us to perform subtraction by means of the addition of a complement. If you wish to subtract 5 from 7, you add the 2’s complement of 5 to 7. The following example uses 8-bit arithmetic to demonstrate two’s complement arithmetic. We will begin by writing down the 2’s complement representations of +5, -5, +7 and -7.

 

+5 = 00000101    -5 = 11111011     +7 = 00000111    -7 = 11111001

 

We can now add the binary value for 7 to the 2’s complement of 5.

 

   00000111                      7

  +11111011                     -5

  100000010                      2

 

The result is 100000010 in nine bits. If we forget about the left-most bit (called the carry bit), the result is 000000102 = +2, which is the number we want. Consider the addition of -7 to +5. In this case we get:

 

   00000101                       5

  +11111001                      -7

   11111110                      -2

 

The result is 11111110 (the carry bit is 0). We would expect the answer to be -2, so let’s calculate the 2’s complement value of -2. The 8-bit binary value corresponding to +2 is 00000010, and its 1’s complement value is 11111101. The 2’s complement of 2 is one greater than the 1’s complement; that is, 11111110, which is the result we are looking for. You may wonder why we don’t say that the result of the addition is 111111102 = 25410. The answer is that if you are using the 2’s complement system to represent signed values, you must interpret the result of an addition or a subtraction as a signed value.

 

The two’s complement system, column E in table 1.3, assigns the values -8 to +7 to the 16 codes 0000 to 1111. It is impossible to represent a signed number outside the range -8 to +7 in 4 bits. If you are using 2’s complement arithmetic and add two positive numbers whose sum greater that 7, the result will be incorrect. Similarly, if you add two negative numbers whose sum is less than -8, the result will also be incorrect. Whenever, a 2’s complement operation is carried out and the result goes out-of-range because it cannot be represented in the available number of bits, arithmetic overflow is said to occur. In 8-bit 2’s complement arithmetic, the range of numbers that can be represented is -128 to +127. In general, an n-bit value can represent signed 2’s complement values in the range -2n-1 to +2n-1-1.

 

When you perform an arithmetic operation you should check that the result is in range and that an overflow error has not occurred. Fortunately, the range of numbers provided by most high-level languages means that arithmetic overflow will seldom cause the high-level language programmer a problem. However, you should be aware of the problem caused by the generation of out-of-range numbers.

 

Although it’s a fascinating topic, we don’t cover 2’s complement arithmetic further. Some of the end of chapter questions explore the characteristics of two complement numbers in greater detail—if you are interested. We will now look at how very large and small numbers are dealt with by a computer. However, some readers may wish to skip this section on a first reading.