Number Systems

From ASM Book

Revision as of 04:58, 19 October 2009 by SpooK (Talk | contribs)
(diff) ← Older revision | Current revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

Introduction

A program consists of two fundamental things: data and instructions. Loosely speaking, a computer represents these data and instructions in the form of numbers. Therefore, it is apparent that a programmer should have a good understanding of the underlying number systems being used by the computer system.

Several number systems, including binary, octal, decimal, and hexadecimal, are used by different computer systems. Before we dive into the other number systems, we would like to cover the most common of them all: the decimal number system. But first, some terminology.


Number Systems

A number system is a way of representing a number. Every number system has a base (the number of digits available). A number system does NOT change the value of the number, but only the manner in which it is represented. What we mean to say is that the value of the number remains the same, but the digits we use and how we use them decides the representation of that number. (You will understand what we mean as we progress along the chapter. For now, just remember, we are only playing with the representation of the number, not its value.)


Base

The base, also called radix or scale, is the fundamental building block of a number system. The base of a number system represents the number of digits it makes available for use. The decimal number system, for example, has 10 digits and is called a base-10 number system. For a number system with base b, the digits 0, ..., b - 1 are used. A table of common bases with the digits they provide follows:

Base Name Digits Last Digit Letter Suffix
2 Binary 0, 1 1 b
8 Octal 0, 1, 2, 3, 4, 5, 6, 7 7 o
10 Decimal 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 9 (none)
16 Hexadecimal 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F F h

Base-0 does not exist and you cannot do much with base-1. A discussion about them is irrelevant to us, so we will avoid them.


Base representation

When you are using several number systems together, it is easy to confuse one number system for another. This is precisely the reason why a subscript suffix is added to a number representation. This makes the number system being used for that particular sequence of digits clear.

There are two common ways of writing the suffix. A decimal number representing the base (10 for the decimal number system) or a letter of the alphabet representing that base (for example, d for the decimal number system). The letter is usually the initial character of the name of the base in use. If a base is not specified, it is usually safe to assume that the number uses the base-10 or decimal number system.

  • Please refer to the above table for information on Bases and Letter Suffixes

A number with base b and the sequence of digits (anan-1a0.a-1...) is represented as:

  (anan-1a0.a-1...)b

Example (the decimal number 44934 in different number systems):

  10101111100001102 -- binary
  1276068           -- octal
  4493410           -- decimal
  af86h             -- hexadecimal

If you look carefully, you will notice the number representation "shrinking" in width as we use a higher number system. Hexadecimal numbers are commonly used in code for precisely this property and because it makes representing numbers simpler (as we shall see later). The lesser the digits we have, the wider the number representation becomes as we have to represent the number using fewer digits. The more the digits we have, the narrower the number representation becomes as we have plenty of digits to represent the number.

The Decimal Number System

The decimal number system is the most commonly used number system. You use it everyday and you have been taught to work with this number system since your childhood. Also called the base-10 number system, the decimal number system offers 10 digits (0 through 9) that one can use to represent numbers.

A number consists of a sequence of one or more digits, with each digit having a weight and a place value. The decimal number, 65535, for example, has 5 digits and 5 corresponding weights each associated with one digit. Starting from the right, the digit 5 has the least weight (i.e 10^0 = 1), that of the digit 3 is 10^1 = 10, that of the digit 5 is 10^2 = 100, and so on toward the left. Each digit occupies a place in the number. The place value is the weight of the digit times the digit. For the digit 3, in 65536, the place value is 3 * 10^1 = 30.

For any number with base b and the sequence of digits (anan-1a0), where n is the place of the digit in the number, the weight, wn, of each digit is given by wn = bn. The place value pn of each digit, an is given by pn = an wn = an bn.

weight of a digit = radix raised to the power of the position of the digit
place value = value of digit * weight of the digit

The Decimal Odometer

If you peek into the dashboard of a vehicle, you will notice a distance measurement device showing the number of miles (or kilometers, in metric units) traveled by that vehicle. That measurement indicator is called an odometer. The next time you go out for a drive, notice how the digits change with each mile you cover.

Consider, for example, a vehicle that has traveled 49,748 miles. Every time the vehicle covers a new mile, that number is incremented by one. Try visualizing it using this graphical illustration as a guide.

  4 9 7 4 8  --  starting
  4 9 7 4 9  --  one more mile covered. the rightmost digit is incremented by one
  4 9 7 4 0  --  one more mile covered. the gears move and the digit 0 is brought into position
  4 9 7 5 0  --  then for the same mile, the gears controlling the second to rightmost digit move
                 and the digit is incremented by 1 from 4 to 5.

If you want to see it for yourself on your computer, try building and running this C program. You will need GCC installed on your system to try this example (for both UNIX and Windows). (If you have the MinGW Compiler system, you don't really need the WIN32-specific part, but we have included it just in case you use a different compiler. Don't forget to define the appropriate preprocessor macro properly when compiling.)

/* odometer.c */
#include <stdio.h>
 
/* choose platform */
#if defined(__WIN32__)
#include <windows.h>
#define sleep(_x) Sleep ((_x)*1000)
#elif defined(__UNIX__)
#include <unistd.h>
#endif
 
 
int
main (void)
{
  register int i = 0;
 
  for (i = 9985; i <= 10000; ++i)
    {
      /* display a number */
      printf ("%05d\r", i);
      fflush (stdout);
 
      /* sleep for 1 second */
      sleep (1);
    }
 
  return 0;
}

Steps to making and running the above program : 1. Put this code in a file named odometer.c

2. To build the executable and run it, do this

For a UNIX system:

  % gcc -g -pedantic -Wall -std=c89 -D__UNIX__ -o odometer odometer.c
  % ./odometer

For a Windows system:

  > gcc -g -pedantic -Wall -std=c89 -D__WIN32__ -o odometer odometer.c
  > odometer

Now, see how the digits change. To stop the running program press Ctrl+C (Windows) or Ctrl-D (UNIX).

You can also use the following Makefile to build this program

  1. --------------------------------------------------------------------------
  2. GNU Makefile.
  3. You need the following software to use this Makefile:
  4. 1. GNU Compiler Collection and GNU Make
  5. Windows - www.mingw.org / www.cygwin.com
  6. UNIX - gcc.gnu.org
  7. 2. rm
  8. Windows - unxutils.sourceforge.net
  9. UNIX - Your UNIX distribution should come with this.
  10. Note: The tabs in the makefile are important!
  11. --------------------------------------------------------------------------

name=odometer platform=-D__WIN32__

CC=gcc CFLAGS=-g -pedantic -Wall -std=c89 RM=rm

  1. --------------------------------------------------------------------------

.PHONY: all clean

all: $(name)

$(name): $(name).c

       @ echo "\n>>> Building program\n"
       $(CC) $(CFLAGS) $(platform) -o $(name) $(name).c

clean:

       @ echo "\n>>> Cleaning build\n"
       - $(RM) -f $(name) $(name).exe *.o

Put the above text in a file called Makefile in the same directory as the odometer.c file and at the command prompt type...

on UNIX:

  % cd source_directory_that_contains_the_code_and_the_makefile
  % make platform=-D__UNIX__
  % ./odometer

on Windows:

  > cd sourcedirectorythatcontainsthecodeandthemakefile
  > mingw32-make
  > odometer


Binary and hexadecimal

Binary and hexadecimal is are both different but yet similar number system which are extremely important to any programmer. Binary is base 2 number system, while hexadecimal is base 16 number system.

The reason for saying why binary is important to a programmer:- In the electronic world, the only practical means to store data is to is the way of on and off (There is no way to tell whether how high is the voltage or how low it is). Therefore in that sense binary is evolved. Data is stored in on or off (1 or 0), so it means that learning binary is learning machine code. (As some people says, "Real man code in binary") Oh yes, there is 10 types of people in the world, one who can read binary and one who cannot.

The reason for saying why hexadecimal is important to a programmer:- It makes no sense to type in 1s and 0s, thus the hexadecimal is evolved. In the sense, it is more practical to adopt a base 16 number system than to use a base 10 number system. By the way, hexadecimal was used to be called sexadecimal, but due to some reasons the people at IBM decided to call it hexadecimal instead. (Some programmers says "Real man codes in hex".)

Binary -> Decimal

Think of reading binary as reading normal number, but in the sense, the numbers mean something else. The last digit means is the to the power 2^0, the second last digit is to the power 2^1 and some one and so forth.

Example:

0000b = 0
0001b = 1
0010b = 2
0011b = 3
0100b = 4
0101b = 5
0110b = 6
0111b = 7
1000b = 8
1001b = 9
1010b = 10

11011010b = 1*2^7 + 1*2^6 + 1*2^4 + 1*2^3 + 1*2^1
          = 128 + 64 + 16 + 8 + 2
          = 218

01010111b = 1*2^6 + 1*2^4 + 1*2^2 + 1*2^1 + 1*2^0
          = 64 + 16 + 4 + 2 + 1
          = 87

(*Note: the b which ends every binary number is used to inform people that the number is in binary, it is just a notation.)

Hexadecimal -> Decimal

Till this point you should be able to understand binary, and since you understand how base 2, you should be able to understand how does hexadecimal works. The conversion of hexadecimal to decimal is almost similar to the conversion of binary to decimal. Well, applying the same concept:-

Example:

01h = 1
02h = 2
03h = 3
04h = 4
05h = 5
06h = 6
07h = 7
08h = 8
09h = 9
0Ah = 10
0Bh = 11
0Ch = 12
0Dh = 13
0Eh = 14
0Fh = 15
10h = 16

F4h = 15*16^1 + 4*16^0
    = 240 + 4
    = 244

F34Ah = 15*16^3 + 3*16^2 + 4*16^1 + A*16^0
      = 15*4096 + 3*256 + 4*16 + 10
      = 61440 + 768 + 64 + 10
      = 62282

(*Note: the h which ends every hexadeciaml number is used to inform people that the number is in hexadecimal, it is just a notation. Some HLL programmers prefer hexadecimal to be prefixed with 0x, but I prefer it to end with h.)

Binary -> Hexadecimal

Now is one of the most important section of the this tutorial. What is the point of knowing binary and hexadecimal exist when you do not know how to convert from one to the other?

Example 1:

0111 1010b
   |   |
7h -   - Ah

Therefore 01111010b -> 7Ah


Example 2:

0100 0111b
: |  |
4h -  - 7h

Therefore 01000111b -> 47h

Personal tools