Understanding Different Base Systems

This essay is targeted at new students of computer programming or computer science who want to understand how base two (binary), base eight (octal), and base sixteen (hexadecimal) work. 

First of all, it's important to realize that each of these base systems is just another way of writing down the same number. When you convert a number between different bases, it should still have the same value. In this essay, when I want to refer to the actual value of a number (regardless of its base), I'll do it in base 10 because that's what most people are used to. 

It's generally easiest to understand the concept of different bases by looking at base 10. When we have a number in base 10, each digit can be referred to as the ones digit, tens digit, the hundreds digit, the thousands digit, or so forth. For instance, in the number 432, 4 is the hundreds digit, 3 is the tens digit, and 2 is the ones digit. 

Another way to think about this is to rewrite 432 as
  4 x 102 + 3 x 101+ 2 x 100
Each digit is multiplied by the next power of ten. Numbers in other bases, such as base 16, are merely numbers where the base is not ten! For instance, we could interpret 432 as though it were in base 16 by evaluating it as
  4 x 162 + 3 x 161+ 2 x 100
This would be the same as the number 1074 in base 10. 

So to convert a number from a given base into base 10, all we need to do is treat each place as a power of the given base times the value of the digit in that place. Note that customarily for a given base, only digits from 0 to the base minus one are used. For instance, in decimal, we only use the digits 0 through 9. That's because we don't need any more digits to express every possible number. (But we do need at least that many; if we only had 8 digits, how would we ever express the value 9?) 

Now, bases greater than 10 will require more than 10 possible digits. For intsance, the number 11 in base ten can be expressed in base 16 with only a single digit because the ones place in base 16 can range from 0 to 15. Since we only have 10 digits, the letters A through F are used to stand for the "digits" 10 through 15. So, for instance, the hexadecimal number B stands for the decimal number 11. 

Bases less than ten will require fewer digits--for instance, binary, which works using powers of two, only needs two digits: one and zero. The binary number 1001, for instance, is the same as writing
 1 * 231 * 221 * 211 * 20
which comes out to the decimal value 9. 

Numbers written in octal use a base of 8 instead of 2 or 16. See if you can figure out what the number 20 written in octal would be in base ten. 

Because octal, hexadecimal, and decimal numbers can often share the same digits, there needs to be some way of distinguishing between them. Traditionally, octal numbers are written with a leading 0; for instance, 020 is the same thing as the number 20 in base 8. Hexadecimal numbers are written with the prefix of "0x". So 0x20 would be the number 20 in base 16; we'd interpret it the same as the decimal number 32.

Converting from decimal to octal or hexadecimal

It turns out that when you wish to convert from decimal to octal or hexadecimal, there is a very easy formula that you can use. I'll give you the one for octal, and let you puzzle out the hexadecimal version (which may come quite naturally to some of you). 

To convert from octal to hexadecimal, all you need to do is group the binary digits into pairs of three and convert each one into the corresponding octal number. For instance, given the binary number 010011110, you would group 011 and 110 together. 010 is 2, 011 is 3 and 110 is 6. So the octal number is 0236. 

So why exactly does this work? Well, let's take a look at what 011110 looks like:
   0 * 28  1 * 27  0 * 26  0 * 25+ 1 * 24+ 1 * 23+ 1 * 22+ 1 * 21+ 0 * 20
That's actually the same as
   0 * 22 * 26+ 1 * 21 * 26+ 0 * 20 * 26+ 0 * 22 * 23+ 1 * 21 * 23+ 1 * 20 * 23+ 1 * 22 * 20+ 1 * 21 * 20+ 0 * 20 * 20
Whoa! First, notice that the far right column is actually turning into powers of 8! 23 is 8, and 26 is 64! So this means for each group of three digits, we have the base increasing by a factor of 8. Moreover, look at the right hand column. It can sum up to at most 7 (since 20 + 21 + 22 = 1 + 2 + 4 and the binary digit just decides whether each power of two is included into the sum or not). That's exactly the same as having eight digits, 0 through 7, and once we sum them all together, we multiply the sum by a power of eight. That's just the same as making each group of three binary digits an octal digit! 

Knowing this, can you come up with the way to do the same thing for hexadecimal numbers? 

'프로그래밍 > C, C++' 카테고리의 다른 글

레슨 1: The basics of C++ ( C++ 의 기본 )  (0) 2011.06.07
구구단 출력 소스 C  (0) 2011.06.07
2진 트리 검색  (0) 2011.06.07
The C Preprocessor  (0) 2011.06.07
The C++ Modulus Operator  (0) 2011.06.07

Binary Search Trees
Binary search trees (also known as just binary trees) are ordered trees in which all nodes have no more than two children. The parent node is always greater than all of the data in the left sub-tree that extends from the left child node, and the parent node is less than all of the data in the right sub-tree that extends from the right child node.

Here is the basic framwork for the binary search tree:

class binTree {
  public:
    binTree(void);         // Constructor
    ~binTree(void);        // Destructor

    void add(int item);    // Add function
    void remove(int item); // Remove function
    bool search(int item); // Search function
    void print(void);      // Print function
  
  private:
    binTreeNode *root;     // Root pointer

    // ...
    // The extra functions needed for implementation are put here
};

class binTreeNode {
  public:
    int data;                 // Actual data
    binTreeNode *left_child;  // Left child pointer
    binTreeNode *right_child; // Right child pointer
};

This code is very similar to the code of the linked list, but the node here is differs from the node to the linked list in that thisbinTreeNode points to two other nodes instead of just one.

Since the left child is always less than the parent and the right child is greater than the parent, the tree can easily print an ordered list of all of the elements with the following algorithm, also known as in-order traversal:

void printTree(binTreeNode *node) {
  printTree(node->left_child);  // Left child first
  cout << node->data << endl;   // Then this node
  printTree(node->right_child); // Then right child
}

To print the tree, you would call the function with the value of root. Each time, the function would keep calling itself (recursion!) until it reaches the leftmost node, which is the least value in the entire tree. Then, it would cycle through the entire tree, and then the right children, until it reaches the rightmost, or greatest, value in the tree.

Other traversals of trees are pre-order and post-order traversals. In pre-order, the root is processed first, then the left children, and then the right children. In post-order, the left children and right children are processed before the root.

Try writing the code for the binary tree as an exercise. It's a little tricky this time, especially with the remove() function. (HINT: Most of the functions require helper, or auxiliary, functions. Some, but definitely not all, of the functions may be recursive.)

'프로그래밍 > C, C++' 카테고리의 다른 글

구구단 출력 소스 C  (0) 2011.06.07
8진수, 16진수의 이해  (0) 2011.06.07
The C Preprocessor  (0) 2011.06.07
The C++ Modulus Operator  (0) 2011.06.07
Getting Random Values in C and C++ with Rand  (0) 2011.06.07

+ Recent posts