Data Representation - Binary

Hexadecimal

Hex digits provide a convenient way to represent 4 bits in a single character and therefore values in the range 0-15. This also means that an 8-bit number can be represented in 2 hex digits, and so on, so hex provides a convenient way to represent numbers which, in binary, would be harder to write down and to interpret. This is important because it can be useful to know certain binary values or their hex equivalents for op-codes in assembly language, for addresses and for signatures such as those for ActiveX objects. It would be much harder to write out and remember these things in binary.

Hexadecimal Character Set

The decimal or denary number base has 10 characters, 0-9, and is also known as 'base 10'. Hexadecimal has 16 characters and so is also known as base 16. The 16 characters are:

Hex 0 1 2 3 4 5 6 7 8 9 A B C D E F
Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

The value of each column of hex digits is a power of 16:

column 3 column 2 column 1 column 0
16 ^ 3 = 4096 16 v^ 2 = 256 16 ^ 1 = 16 16 ^ 0 = 1
Base 16 and Conversions to Decimal and Binary

Where you have two hex digits together the decimal value can be worked out as follows:

Hex Value: 3F ; decimal value:  3 * 16^1 + F * 16^0 = 3*16 + 15*1= 48+15 = 63

In binary: 3=0011, F=1111 so 3F=00111111 = 1+2+4+8+16+32=63. Check!

Hex value: BD ; decimal value:  B * 16^1 + D * 16^0 = 11 * 16 + 13 * 1 = 189

In binary: 1011 1101 = 1+4+8+16+32+128=189. Check!

Four hex digits:

Hex value: C4FA ; decimal value: C*16^3 + 4*16^2 + F*16^1 + A*16^0 =

 12*4096 + 4*256  + 15*16 + 10*1  = 50,426

Binary: 1100 0100 1111 1010

Negative Numbers

One's Complement

One way to represent a negative number is to invert or complement it:

00111100 (60) becomes 11000011 (each bit changes to its opposite). This is known as 'one's complement'

The number 11000011 is interpreted as negative because its left-most bit is 1 - this is the sign bit.

With negative numbers available it is possible to perform subtraction by adding the complement, e.g. 5-2 becomes 5 + (-2).

The problem with one's complement is that subtractions do not give the correct answer unless 1 is added afterwards.

Two's Complement

A second step is used, therefore, which is to add 1 to the one's complement, thus producing the 'two's complement' value. Thus -60 is:

00111100 -> 11000011 (1's complement for -60) -> 11000100 (2's complement for -60)

To go from two's complement to decimal and back:

11101100 -> 00010011 (invert=19) -> 00010100 (add 1 = 20) -> 11101011 (one's complement) -> 11101100 (2's complement)

For example: 60: 00111100 -> 11000011 (1's complement) -> 11000100 (2's complement)
  -> 00111011 (inverse=59) -> 00111100 (add 1 = 60)

Fractions

Fixed Point Fractions

In decimal a fraction is expressed as a negative power of 10:

0.1=10^(-1), 0.01=10^(-2), 0.5=10^(-0.30106), etc.

In binary a fraction is expressed as a negative power of 2:

0.5=2^(-1), 0.25=2^(-2), 0.125=2^(-3), etc.

A number such as 0.75 is the sum of negative powers of 2: 0.5 + 0.25 = 2^(-1) + 2^(-2).

These fractions are examples of fixed point numbers, the fractional point is always in the same place:

1 0.5 0.25 0.125 0.0625 0.03125 0.015625
2^0 2^(-1) 2^(-2) 2^(-3) 2^(-4) 2^(-5) 2^(-6)

Fixed point fractions are of limited use in real computing because they can only produce values in the range of the bits available. If 4 bits are available for the fractional part then the possible values are 0.5, 0.25, 0.125 and 0.0625 (1/2. 1/4/, 1/8 and 1/16). Thus the range of values that can be produced is 1/16 to 15/16. For wider ranges of values floating point representation is to be preferred and this is the usual method for storing fractions (and also very large numbers).

Floating Point Numbers

The range of binary numbers that can be stored in a given number of bits can be extended by using the floating point method. This splits a number into two parts, the mantissa and the exponent. The mantissa holds the details of the number (the digits) while the exponent holds the number of places the fractional point has been moved. Moving (or floating) the fractional point means that a number can be scaled to be very big or very small.

The value of a floating point number can then be calculated from: number = mantissa * base ^ exponent

For example:

12 * 10 ^ 2 = 1200;

In scientific notation: 1.2 * 10 ^ 3 = 1200; or, more likely, 1.23456 * 10 ^ 20 or 1.23456E20; or 1.23456E-15.

0.5 * 2 ^ 4 = 8;

1000 * 2 ^ 0100 = 8; (binary values so 1000 is 0.5, 2^0100=16)

Conventions

The range of values that a floating point number can represent depends on the number of bits available and on the conventions adopted for the use of sign bits and the position of the fractional point.

The convention for the mantissa is that it is a fraction, so 1000 is 0.5. The 1000 representation of the mantissa is more commonly seen as 0.100, that is with a sign bit to the left of the point and, in this case, three bits to the right.

With a mantissa of 0111 and an exponent of 0000 the value of the number will be 0.875, the sum of the bits in the mantissa, that is:

0.875 * 2 ^ 0 = 0.875

With an exponent of 0001 the number is 0.875 * 2 ^ 1 = 0.875 * 2 = 0.75; with an exponent of 0010 the number is 0.875 * 2 ^ 2 = 0.875*4 = 3.

Implementations

The way the components are divided is a matter of implementation. Another approach might be to store the mantissa in sign and magnitude format, that is with a sign bit of 0 or 1 followed by the value of the mantissa, with no complementing.

In this case a value of 1111 in the mantissa would mean something completely different. The left-most 1 denotes a negative number and the next three bits are 0.5 + 0.25 + 0.125 = 0.875, that is -0.875 * 2 ^ 0 = -0.875.

When a number is converted to floating point it is 'normalised' so that the fractional point is in the same place each time. Each place movement of the fractional point is translated as an addition to the value of the exponent.

Examples

1.5 becomes: mantissa = 0110 ; exponent = 0001. Explanation: the left-most bit is 0 so the mantissa is positive; the fractional point comes between the left-most bit and the next bit: 0.110; the exponent is 0001 so the number is (0.5+0.25) = 0.75 * 2 ^ 1 = 1.5; alternatively, the exponent of 0001 says 'move the fractional point one place right, giving 01.10, which is 1.5.

15 becomes: mantissa: 0111 ; exponent: 0100, or 0.875 * 2 ^ 4 = 14 (No misprint!). Explanation: the sign bit is zero, the three ones have a value of 0.5+0.25+0.125=0.875; 0.875 * 2 ^ 4 = 14; to make 15 accurately we need one more bit in the mantissa to give us 01111 0100, but we don't have it; 0.5+0.25+0.125+0.0625=0.9375; 0.9375 * 2 ^ 4 = 15.

Thus in our system of 4-4 with a sign bit on the mantissa we cannot represent 15 exactly. This is a problem with floating point, whatever scale we use there will be 'holes' in the representation of values, approximations, roundings and inaccuracies. (As a matter of interest 0.5 * 2 ^ 5 = 16, 15 is still missing.)

Normalisation

When a number is stored in floating point format it is normalised by scaling it so that there is a '1' in the most significant bit of the mantissa while the exponent stores the number of points the number has moved to achieve this. When the number is converted back to its decimal value the exponent provides the number of places to move the fractional point. For numbers smaller than 0.5 the exponent will be negative and the fractional point must move left as the number is calculated. For example, 0.125 will be stored in 8 bits as 0100 1110 (mantissa/exponent)  = 0.5 * 2 ^ (-2).

The benefits of normalisation are:

Further Examples: 16 bits

Stepping up to a 16 bit number with 8 bits each for the exponent and mantissa and 2's complement in the mantissa we might have:

7D03 in hex = 01111101 00000011 in binary, mantissa=01111101, exponent=00000011

To convert this to decimal: sign bit of mantissa is positive so no need to convert; exponent is 3 so move fractional point of mantissa 3 places to the right from between the sign bit and the most significant bit: 0111.1101 = 7.8125.

If the exponent were negative, for example 7DFD: mantissa as before; exponent is 2's complement negative number so invert: 11111101 -> 00000010, add 1: 00000011=3; exponent is -3 so move fractional point 3 places left of current fractional point, inserting additional zeroes: 0.0001111101 = 1/16+1/32+1/64, etc. (a smallish fraction and unlikely to appear in an exam).

AE04 in hex = 1010 1110 0000 0100 in binary, mantissa=10101110, exponent=00000100.

To convert this to decimal: Sign bit is negative so convert number from 2's complement: invert: 01010001, add 1: 01010010; exponent is 4 so move fractional point 4 to right: 01010.010 = 10.25; number was negative so value is -10.25.

Alternative process: mantissa=10101110, exponent=00000100; exponent is 4 so move fractional point 4 places to the right: 10101.110 = -16+4+1+0.5+0.25 = -10.25 (in this method count the most significant bit as minus n and the other 1 bits as their positive value).

For successful conversions like this you need to know the conventions used, whether sign and magnitude or 2's complement for negative numbers. Assume 2's complement unless told otherwise.

Convert decimal to Binary Floating Point

e.g. 2.5. In binary: 00101000 (that is, 4 bits for integer part: 0010=2; 4 bits for fractional part: 1000=0.5). Normalised: 01010000, mantissa = 2; 0.1010000 = 0.5+0.125 = 0.625*4 = 2.5.

e.g. 13. In binary: 00001101; this becomes 01101 = 0.5 + 0.25 + 0.0625 =  0.8125; mantissa = 0100 (4, the number of places the fractional point must move to make 00001101).

e.g. 45. In binary: 00101101; this becomes 0.101101 with mantissa 6 or 1100; this is 0.703125 x 2^6 (64) = 45.

Convert the following to binary floating point (10 bits each for mantissa, 6 for exponent): 27, 4.5, 5.75, 10, 200, 190.125.

Four Permutations

Note that there are four permutations of mantissa and exponent:

positive mantissa, positive exponent: positive number >=1

positive mantissa, negative exponent: positive fraction <1

negative mantissa, positive exponent: negative number <=-1

negative mantissa, negative exponent: negative fraction

Convert the following to floating point:

12.875

0.375

-37.765625

-0.65625