Learn how to count in any numbering system

In this blog post, I will teach you how to count in any numbering system. I have also created a program that counts in any numbering system and I will show you this program in the second part of this blog post.

I have  a shared folder pertaining  to this blog post that you are free to visit and download its contents. You may visit the shared folder at the following link: Count in any numbering system. In this folder, you will find:

  • An Excel spreadsheet with two tabs, that may help you in your learning.
  • A text file that contains the source code of the program (in C# with .NET framework version 2.0) that counts in any numbering system.
  • A zip file that contains the complete Visual Studio Windows Forms C# project (that also contains the source code of the program that counts in any numbering system.)
  • An executable file, which is the Windows program that counts in any numbering system. You can copy the executable file in any folder of your Windows OS and run it. It needs no installation, but you need to have the Windows .NET framework (version 2.0 at least) in order to execute the program.

OK. First things first: How to count in any numbering system.

We (humans) use the base-10 numbering system. Why? Well, all numbering systems are equivalent, but we chose the base-10 numbering system because we have ten fingers, and we find counting in tens to be more intuitive and convenient. We are used to counting in tens, so we chose a numbering system that corresponds to this counting manner.

If we were a species with three fingers (three fingers altogether, and to keep the symmetry we might have had three hands, each hand having only finger, or only one hand with three fingers, or even two hands, one with two fingers and the other hand with only one finger, but then these two hands might be in opposite directions in order to keep the symmetry of our body) we might have chosen to use the base-3 numbering system for counting, because we would want to count in threes.

The smallest base that can exist is base-2. In base-2, we have two digits: 0, 1.

In base-3, we have three digits: 0, 1, 2.

And so on.

In base-10, we have 10 digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

In base-11, we have 11 digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A. (We use letters because we run out of number symbols. Actually we may use any symbol for any number. So, if, for example, we replace 0 with &, and 1 with *, and 2 with %, etc, we will have an equivalent representation).

In base-16, we have 16 digits:  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.

And so on.

Here is how to count in any-numbering system:

Example in base-2, which means that the digits are 0, 1.

Start from 0, which is equal to infinite zeros: …000000

Increase the rightmost digit.

...000000
...000001

When the rightmost digit cannot increase any more,
set the rightmost digit to zero
and increase the second rightmost digit.

...000010

Continue to increase the rightmost digit,
keeping the other digits as they are.

...000011

When the rightmost digit cannot increase any more,
set the rightmost digit to zero
and increase the second rightmost digit.
But if the second righmost digit cannot increase anymore,
set it to zero as well
and increase the third rightmost digit.

...000100

And so on:

...000101
...000110
...000111
...001000
...001001
...001010
...001011
...001100
...001101
...001110
...001111
...010000
...010001
.........

And so on…

Example in base-3, which means that the digits are 0,1,2.

Start from 0, which is equal to infinte zeros: …000000

Increase the rightmost digit.

...000000
...000001
...000002

When the rightmost digit cannot increase any more,
set the rightmost digit to zero
and increase the second rightmost digit.

...000010

Continue to increase the rightmost digit,
keeping the other digits as they are.

...000011
...000012

When the rightmost digit cannot increase any more,
set the rightmost digit to zero
and increase the second rightmost digit.

...000020

Continue to increase the rightmost digit,
keeping the other digits as they are.

...000021
...000022

When the rightmost digit cannot increase any more,
set the rightmost digit to zero
and increase the second rightmost digit.
But if the second righmost digit cannot increase anymore,
set it to zero as well
and increase the third rightmost digit.

...000100

And so on:

...000101
...000102
...000110
...000111
...000112
...000120
...000121
...000122
...000200
...000201
...000202
...000210
...000211
...000212
...000220
...000221
...000222
...001000
...001001
...001002
...001010
...001011
...001012
...001020
...001021
...001022
...001100
...001101
...001102
...001110
...001111
...001112
...001120
...001121
...001122
...001200
...001201
...001202
...001210
...001211
...001212
...001220
...001221
...001222
...002000
...002001
...002002
...002010
...002011
...002012
...002020
...002021
...002022
...002100
...002101
...002102
...002110
...002111
...002112
...002120
...002121
...002122
...002200
...002201
...002202
...002210
...002211
...002212
...002220
...002221
...002222
...010000
...010001
.........

And so on…

Additional notes:

So now you know how to produce the numbers of any base in ascending order. There is another way to produce the numbers of any base in ascending order. This is done by writing vertically each digit column starting from the rightmost digit column. So, you create the rightmost digit column by writing each number once starting from 0 then 1 and so on. When the digits finish, you start over. So, for base 2, you write:

....0
....1
....0
....1
....0
....1
....0
....1
.....

Then you create the second rightmost column by noticing the repeating pattern of the rightmost column and matching it with one digit in the second rightmost column, starting from zero. The repeating pattern of the rightmost column is 0-1. So you create the second rightmost column as follows:

...00
...01
...10
...11
...00
...01
...10
...11
.....

As you may notice, the repeating pattern of the second rightmost column is 0-0-1-1.

So you create the third rightmost column as follows:

..000
..001
..010
..011
..100
..101
..110
..111
.....

The repeating pattern of the third rightmost column is 0-0-0-0-1-1-1-1.

And so on.

For base-3, the repeating pattern of the rightmost column would be 0-1-2. The repeating pattern of the second rightmost column would be 0-0-0-1-1-1-2-2-2. The repeating pattern of the third rightmost column would be 0-0-0-0-0-0-0-0-0-1-1-1-1-1-1-1-1-1-2-2-2-2-2-2-2-2-2. And so on.

Counting is important and base-2 and bases that are powers of 2, especially base-16, are very important when dealing with digital electronics and computers in low-level.  Let me explain why.

First of all, computers are created as large bundles of electronic switches. Switches, electronic or otherwise, have two states: off and on. So, engineers assign the number 0 to one of the states and the number 1 to the other state (in a consistent manner, of course) and can set each switch to any state or read any switch’s state. That’s how computations are made at a low-level. So, binary arithmetic is essential to enginners for the programming and operation of a computer. The state of each electronic switch is either 0 or 1, and 0 and 1 are the “binary” digits, or bits as they called in computer parlance. Just for your information, each electronic switch is made up from a few transistors, which can me made really tiny. A computer chip may contain billions of transistors.

OK, so base-2 and the corresponding arithmetic (binary arithmetic) of this numbering system is important to computers, But why is base-16 (hexadecimal arithmetic) also important? Well, the numbering systems of the powers of the same base have an important connection. I will now explain what this connection is. For example, let us take the number 2. The numbering systems that are powers of 2 are: base-2, base-4, base-8, base-16, base-32, base-64, and so on. The conversion between any of these numbering systems to another such system can be easily done.

Here is how: Let us study base-2 and base-16. suppose we have a number in base-16, for example B8. What is this number in base-2? To answer, we will represent each of the hexadecimal digits with 4 binary digits, since we need 4 binary digits to represent the highest hexadecimal digit (F in base-16 is 1111 in base-2). So, we have the number B8, and B in base-16 is 1011 in base-2, and 8 in base-16 is 1000 in base-2. The important property of numbering systems of powers of the same base allows us to find a number’s equal in another such base, as follows: We substitute each digit from the higher base to the equivalent digits of the lower base, or we group the digits of the lower base to the equibalent digits of the higher base. In the case of the base-16 number B8, it is equal to 10111000 in base-2, where the first four binary digits correspond to B and the next 4 binary digits correspond to 8.

Another example: Given the base-2 number 110100011, what is the equivalent base-16 number? Well we will group the digits by four’s, starting from the right and adding leading zeros if we need to. So our number becomes: 0001 1010 0011. Substituting each group of 4 digits with its hexadecimal equivalent gives us the base-16 number 1A3.

This property is very important to computing and one of the reasons engineers chose to represent information in bytes. Each byte is an ordered set of 8 bits. By choosing bytes to be comprised of 8 bits each, it makes their representation very easy: Each byte can be represented by two hexadecimal digits. So a byte with the following value in bits: 00100100, can be represented as 24 in hexadecimal (base-16).

I found that knowing how to count in base-2 was enough to solve any IP (Internet Protocol) subnetting problem that I ever encountered! Of course, it will be very beneficial to you if you learn how to do other operations as well (beyond counting, like addition, subtraction, multiplication, division, transformation of a number from one base to another). And, if you will be dealing with computers, you may often encounter base-2 and base-16 number representations.

My program which counts in any numbering system

I created a program in C# that counts in any numbering system. I will present the code below and you can also download the code or even the complete Visual Studio project from the link I provide in the beginning of this blog post.

If you want to recreate the project yourself, just create a new project in Visual Studio as a Windows Forms C# application. In a form place two textboxes, a button and a DataGridView. You may also place two labels, to show what each textbox use is. And then, use my code as the form’s code.

You, may see what the form looks like below:

In the first textbox, you enter the base for which you want to count. Counting will start from 0 up to the number you want. You must specify this number in its base-10 representation in the second textbox. When you press the button, the program will create two columns in the datagridview. The first column will contain the numbers in base-10 for your reference and the second column will contain the equivalent numbers in the base you specified in the first textbox.

In the code you will see that there is a string (array of characters) called strDigitSymbols. These are the digits that the program uses to construct the numbers in the second datagridview column. So, even if the program “knows” for sure it “wants” to use a 0 or a 1 in the second gridcolumn, it will never put 0 or 1, but instead it will put  strDigitSymbols.Substring(0, 1) instead of 0 and strDigitSymbols.Substring(0, 1) instead of 1. This is because I want to let the user specify alternate symbols, should she wish to do so. Thus, whereas the “normal” strDigitSymbols would be “0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ”, the user is allowed to replace it with whatever string she wishes, for example “%#*@(F4SL!)-+0=”, No, this is not swearing, it is a string with 15 characters, which means that the program can count for bases up to base-15. The string I have put in the program contains 36 characters, which means that the program, as is, can count up to base-36. You can add more digits to the string, so you can request counting in even larger bases. The program can count up to the base that has the same number as the number of digits that exist in strDigitNumbers.

As for the first datagridview column, it is in base-10 for your reference and does not look in the strDigitSymbols to get its symbols. The program uses regular good old decimal digits for the first datagridview column.

Here is the code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Count
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            const string strDigitSymbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

            dataGridView1.Rows.Clear();
            dataGridView1.Columns.Clear();
            dataGridView1.Refresh();

            bool isNumerical;

            int intBase = 0;

            isNumerical = false;
            isNumerical = int.TryParse(textBox1.Text, out intBase);
            if (!isNumerical)
            {
                MessageBox.Show("The base number must be an integer equal or greater than 2", "Error in the base number: Not an integer.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (intBase < 2) { MessageBox.Show("The base number cannot be less than 2.", "Error in the base number: Too small.", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (intBase > strDigitSymbols.Length)
            {
                MessageBox.Show("There are not enough digit symbols to represent the numbers for the base number you requested.", "Error in the base number: Too big.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            int intMaximumCount = 0;

            isNumerical = false;
            isNumerical = int.TryParse(textBox2.Text, out intMaximumCount);
            if (!isNumerical)
            {
                MessageBox.Show("The number in base-10 to count up to must be a positive integer", "Error in the count number: Not an integer.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            dataGridView1.Columns.Add("Base 10", "Base 10");
            dataGridView1.Columns.Add("Requested Base", "Requested Base");

            dataGridView1.Columns["Base 10"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomRight;
            dataGridView1.Columns["Requested Base"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomRight;

            dataGridView1.Columns["Base 10"].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomRight;
            dataGridView1.Columns["Requested Base"].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomRight;

            string strPreviousNumber = strDigitSymbols.Substring(0, 1);

            dataGridView1.Rows.Add(0, strPreviousNumber);

            string strNextNumber;
            string strDigit;
            string strNextDigit;
            int i;
            bool blnFinished = false;

            for (int intCount = 1; intCount <= intMaximumCount; intCount++)
            {

                // We begin each for iteration with the strPreviousNumber set at the end of the pevious for iteration.
                // The goal of each for iteration is to find the strNextNumber, which is the number that succeds the strPreviousNumber.

                strNextNumber = "";
                strDigit = "";
                strNextDigit = "";
                i = 0;
                blnFinished = false;

                // We will get each digit of the previous number starting from the right of the previous number,
                // using i as the counter to access the digits of the previous number.

                while (true)
                {
                    // Get next digit of the previous number from the left.

                    strDigit = strPreviousNumber.Substring(strPreviousNumber.Length - 1 - i, 1);

                    // For the digit obtained, find the coresponding digit that succeeds it,
                    // using j as the counter to scan strDigitSymbols.

                    for (int j = 0; j <= intBase - 1; j++)
                    {
                        if (strDigit == strDigitSymbols.Substring(j, 1))
                        {
                            // We found the digit and now we will take the corresponding digit that suceeds it and then we will break from the inner for loop.

                            if (j < intBase - 1) { // If we are here, it means that we have the "normal" case where the next digit is greater than the previous digit. // Example in Base-10: strDigit = "6", thus strNextDigit = "7". // Because this kind of incementation will happen, we will set blnFinished to true, in order to break from the while loop. strNextDigit = strDigitSymbols.Substring(j + 1, 1); if (strPreviousNumber.Length - 1 - i > 0)
                                {
                                    // If we are here, it means that there are more digits of the previous number to the left of the digit we are processing.

                                    strNextNumber = strPreviousNumber.Substring(0, strPreviousNumber.Length - 1 - i) + strNextDigit + strNextNumber;
                                }
                                else
                                {
                                    // If we are here, it means that there no are more digits of the previous number to the left of the digit we are processing.

                                    strNextNumber = strNextDigit + strNextNumber;
                                }

                                // We finished processing and we need to break from the while loop.

                                blnFinished = true;
                            }

                            if (j == intBase - 1)
                            {
                                // If we are here, it means that the next digit is the first in strDigitSymbols.
                                // Example in Base-10: strDigit = "9", thus strNextDigit = "0".\
                                // Because this kind of incementation will happen, we will not set blnFinished to true, in order to continue looping in the while loop.

                                strNextDigit = strDigitSymbols.Substring(0, 1);
                                strNextNumber = strNextDigit + strNextNumber;
                            }

                            break; // Break from the inner for loop.

                        } // End of the outer if statement.

                    } // End of the inner for loop.

                    if (blnFinished == true)
                    {
                        break; // Break from the while loop.
                    }

                    i++;

                    if (i == strPreviousNumber.Length)
                    {
                        break; // Break from the while loop because there are no more digits to process.
                    }

                } // End of the while loop.

                if (blnFinished == false)
                {
                    // If we are here, it means that all digits have been turned to zero,
                    // so we need to add a "1" in front of all these zeros.
                    // Example in Base-10: strPreviousNumber = "9999", thus strNextNumber = "10000".

                    strNextNumber = strDigitSymbols.Substring(1, 1) + strNextNumber;
                }

                dataGridView1.Rows.Add(intCount, strNextNumber);

                // We begin each for iteration with the strPreviousNumber set at the end of the pevious for iteration.
                // The goal of each for iteration is to find the strNextNumber, which is the number that succeds the strPreviousNumber.

                strPreviousNumber = strNextNumber;

            } // End of the for loop.

        } // End of the button1_Click.

    } // End of the class.

} // End of the namespace.

The outer for loop is used to count from 0 to the decimal number in the second textbox. This represents up to how many numbers we will count. The counter for this for loop is a regular decimal numbers and is used to populate the first datagridview column for your reference. In each outer for loop iteration, the program finds the number that will go in the second datagridview column, based in the base you requested in the first textbox. How does the program find the number in the requested base? Well, the first number is 0, or, rather, the first number in strDigitSymbols. In each outer for loop iteration it uses the knowledge of  what the previous number was and it scans the previous number’s digits as well as the strDigitSymbols digits, to deduce the “current” number.

The program never breaks form the outer for loop. The loop continues until it reaches the number you have specified in the second textbox.

In each for loop iteration, the program uses a while loop to scan the digits of the previous  and an inner for loop to scan the strDigitSymbols. This way, the program can deduce the next number in the sequence.

The program is heavily commented, so you may understand its inner workings.

Advertisements

About Dimitrios Kalemis

I am a systems engineer specializing in Microsoft products and technologies. I am also an author. Please visit my blog to see the blog posts I have written, the books I have written and the applications I have created. I definitely recommend my blog posts under the category "Management", all my books and all my applications. I believe that you will find them interesting and useful. I am in the process of writing more blog posts and books, so please visit my blog from time to time to see what I come up with next. I am also active on other sites; links to those you can find in the "About me" page of my blog.
This entry was posted in Development. Bookmark the permalink.