CSharp: Understanding the HexaTriDecimal numbering system and generating HexaTriDecimal numbers

From CodeMinima <Code Concised>
Jump to: navigation, search
I LOVE CODEMINIMA!

C#: Understanding the HexaTriDecimal numbering system and generating HexaTriDecimal numbers

Contents

Description

This C# code sample demonstrates how to generate very large HexaTriDecimal numbers. HexaTridecimal is a base-36 numbering system that uses 36 as its base radix. To this end, we use "standard" Arabic numerals (0 through 9) followed by Latin letters (A through Z). The most beneficial feature of using the HexaTriDecimal numbering system is that it solely uses ASCII characters that are available on any standard keyboard.

Prerequisites

  1. C# compiler with any standard ASCII editor like Notepad, or
  2. Visual Studio Express with C# compiler, or
  3. Visual Studio.Net or better with C# compiler.

Code

  1. using System;
  2.  
  3. public class HexaTriDecimalType {
  4.     #region << Constants >>
  5.  
  6.     const int DEF_WIDTH = 10;
  7.  
  8.     #endregion << Constants >>
  9.  
  10.     #region << Members >>
  11.  
  12.     int _width = DEF_WIDTH;
  13.     char[] _places;
  14.  
  15.     #endregion << Members >>
  16.  
  17.     #region << Properties >>
  18.  
  19.     public int Width {
  20.         get {
  21.             return _width;
  22.         }
  23.     }
  24.  
  25.     #endregion << Properties >>
  26.  
  27.     #region << Constructors >>
  28.  
  29.     public HexaTriDecimalType () {
  30.         _places = new char[_width];
  31.         for (int i = 0; i < _width; ++i) {
  32.             _places[i] = '0';
  33.         }
  34.     }
  35.  
  36.     public HexaTriDecimalType (int width) {
  37.         _width = width;
  38.         _places = new char[_width];
  39.         for (int i = 0; i < _width; ++i) {
  40.             _places[i] = '0';
  41.         }
  42.     }
  43.  
  44.     public HexaTriDecimalType (HexaTriDecimalType a) {
  45.         _width = a._width;
  46.         _places = new char[_width];
  47.         for (int i = 0; i < _width; ++i) {
  48.             _places[i] = a._places[i];
  49.         }
  50.     }
  51.  
  52.     public HexaTriDecimalType (string numberAsString, int width) {
  53.         _width = width;
  54.         _places = new char[_width];
  55.         for (int i = 0; i < _width; ++i) {
  56.             _places[i] = '0';
  57.         }
  58.  
  59.         Parse (numberAsString);
  60.     }
  61.  
  62.     public HexaTriDecimalType (string numberAsString) {
  63.         _places = new char[_width];
  64.         for (int i = 0; i < _width; ++i) {
  65.             _places[i] = '0';
  66.         }
  67.  
  68.         Parse (numberAsString);
  69.     }
  70.  
  71.     #endregion << Constructors >>
  72.  
  73.     #region << External Utils >>
  74.  
  75.     public static string GetNextNumber (string number) {
  76.         foreach (char ch in number) {
  77.             if (!IsLegalChar (ch)) {
  78.                 throw new Exception ("Illegal characters in string.");
  79.             }
  80.         }
  81.  
  82.         string numberAsString = ConvertToUpperCase (number);
  83.         HexaTriDecimalType htd = null;
  84.         try {
  85.             htd = new HexaTriDecimalType (numberAsString, numberAsString.Length);
  86.             htd++;
  87.         } catch (Exception) {
  88.             htd = new HexaTriDecimalType (numberAsString, numberAsString.Length + 1);
  89.             htd++;
  90.         }
  91.  
  92.         return htd.ToString ();
  93.     }
  94.  
  95.     #endregion << External Utils >>
  96.  
  97.     #region << Internal Utils >>
  98.  
  99.     private void Parse (string numberAsString) {
  100.         if (numberAsString.Length > _width) {
  101.             throw new Exception ("Size exceeds width.");
  102.         }
  103.  
  104.         foreach (char ch in numberAsString) {
  105.             if (!IsLegalChar (ch)) {
  106.                 throw new Exception ("Illegal characters in string.");
  107.             }
  108.         }
  109.  
  110.         string num = ConvertToUpperCase (numberAsString);
  111.  
  112.         for (int i = _places.Length - 1; i >= _places.Length - num.Length; --i) {
  113.             _places[i] = num[i - (_places.Length - num.Length)];
  114.         }
  115.     }
  116.  
  117.     private static string StripOffInsignificantChars (string number) {
  118.         int sigIndex = 0;
  119.         for (int i = 0; i < number.Length; ++i) {
  120.             char ch = number[i];
  121.             if (ch == '0') {
  122.                 ++sigIndex;
  123.             } else {
  124.                 break;
  125.             }
  126.         }
  127.  
  128.         return number.Substring (sigIndex, number.Length - sigIndex);
  129.     }
  130.  
  131.     private static char[] StripOffInsignificantChars (char[] array) {
  132.         int sigIndex = 0;
  133.         for (int i = 0; i < array.Length; ++i) {
  134.             if (array[i] == '0') {
  135.                 ++sigIndex;
  136.             } else {
  137.                 break;
  138.             }
  139.         }
  140.  
  141.         char[] opArray = new char[array.Length - sigIndex];
  142.         int index = 0;
  143.         for (int i = sigIndex; i < array.Length; ++i) {
  144.             opArray[index++] = array[i];
  145.         }
  146.  
  147.         return opArray;
  148.     }
  149.  
  150.     private static bool IsLegalChar (char ch) {
  151.         if (Char.IsDigit (ch) || Char.IsLetter (ch)) {
  152.             return true;
  153.         }
  154.  
  155.         return false;
  156.     }
  157.  
  158.     private static string ConvertToUpperCase (string numberAsString) {
  159.         string opStr = string.Empty;
  160.  
  161.         for (int i = 0; i < numberAsString.Length; ++i) {
  162.             char ch = numberAsString[i];
  163.             if (ch >= 'a' && ch <= 'z') {
  164.                 ch -= (char) 32;
  165.             }
  166.             opStr += ch;
  167.         }
  168.  
  169.         return opStr;
  170.     }
  171.  
  172.     #endregion << Internal Utils >>
  173.  
  174.     #region << Increment Operation >>
  175.  
  176.     public static HexaTriDecimalType operator ++ (HexaTriDecimalType a) {
  177.         a.IncrementByOne ();
  178.         return a;
  179.     }
  180.  
  181.     private void IncrementByOne () {
  182.         IncrementByOne (_width - 1);
  183.     }
  184.  
  185.     private void IncrementByOne (int place) {
  186.         if (place < 0) {
  187.             throw new Exception ("Maximum value reached.");
  188.         }
  189.  
  190.         char ch = _places[place];
  191.         if ((ch >= '0' && ch <= '8') || (ch >= 'A' && ch <= 'Y')) {
  192.             _places[place] = ++ch;
  193.         } else if (ch == '9') {
  194.             _places[place] = 'A';
  195.         } else if (ch == 'Z') {
  196.             _places[place] = '0';
  197.             IncrementByOne (place - 1);
  198.         }
  199.     }
  200.  
  201.     #endregion << Increment Operation >>
  202.  
  203.     #region << Decrement Operation >>
  204.  
  205.     public static HexaTriDecimalType operator -- (HexaTriDecimalType a) {
  206.         a.DecrementByOne ();
  207.         return a;
  208.     }
  209.  
  210.     private void DecrementByOne () {
  211.         DecrementByOne (_width - 1);
  212.     }
  213.  
  214.     private void DecrementByOne (int place) {
  215.         if (place < 0) {
  216.             throw new Exception ("Minimum value reached.");
  217.         }
  218.  
  219.         char ch = _places[place];
  220.         if ((ch >= '1' && ch <= '9') || (ch >= 'B' && ch <= 'Z')) {
  221.             _places[place] = --ch;
  222.         } else if (ch == 'A') {
  223.             _places[place] = '9';
  224.         } else if (ch == '0') {
  225.             _places[place] = 'Z';
  226.             DecrementByOne (place - 1);
  227.         }
  228.     }
  229.  
  230.     #endregion << Decrement Operation >>
  231.  
  232.     #region << Comparison Operations >>
  233.  
  234.     public static bool operator == (HexaTriDecimalType lhs, HexaTriDecimalType rhs) {
  235.         if (lhs.Width != rhs.Width) {
  236.             return false;
  237.         }
  238.  
  239.         for (int i = 0; i < lhs.Width; ++i) {
  240.             if (lhs._places[i] != rhs._places[i]) {
  241.                 return false;
  242.             }
  243.         }
  244.  
  245.         return true;
  246.     }
  247.  
  248.     public static bool operator == (HexaTriDecimalType lhs, string rhs) {
  249.         string sigRhs = ConvertToUpperCase (StripOffInsignificantChars (rhs));
  250.  
  251.         char[] rhsPlaces = sigRhs.ToCharArray ();
  252.         char[] lhsPlaces = StripOffInsignificantChars (lhs._places);
  253.  
  254.         if (lhsPlaces.Length != rhsPlaces.Length) {
  255.             return false;
  256.         }
  257.  
  258.         if (lhsPlaces.Length == rhsPlaces.Length) {
  259.             for (int i = 0; i < lhsPlaces.Length; ++i) {
  260.                 if (lhsPlaces[i] != rhsPlaces[i]) {
  261.                     return false;
  262.                 }
  263.             }
  264.         }
  265.  
  266.         return true;
  267.     }
  268.  
  269.     public static bool operator != (HexaTriDecimalType lhs, HexaTriDecimalType rhs) {
  270.         return !(lhs == rhs);
  271.     }
  272.  
  273.     public static bool operator != (HexaTriDecimalType lhs, string rhs) {
  274.         return !(lhs == rhs);
  275.     }
  276.  
  277.     #endregion << Comparison Operations >>
  278.  
  279.     #region << Overrides >>
  280.  
  281.     public override string ToString () {
  282.         string opStr = string.Empty;
  283.  
  284.         for (int i = 0; i < _width; ++i) {
  285.             opStr += _places[i];
  286.         }
  287.  
  288.         return opStr;
  289.     }
  290.  
  291.     public override int GetHashCode () {
  292.         return base.GetHashCode ();
  293.     }
  294.  
  295.     public override bool Equals (object obj) {
  296.         return base.Equals (obj);
  297.     }
  298.  
  299.     #endregion << Overrides >>
  300. }
  301.  
  302. class Program {
  303.     static void Main (string[] args) {
  304.         HexaTriDecimalType h1 = new HexaTriDecimalType ();
  305.  
  306.         Console.WriteLine ("Simple increment operation:");
  307.         for (int i = 0; i < 50; ++i) {
  308.             Console.WriteLine ("{0}: {1}", i, h1);
  309.             ++h1;
  310.         }
  311.  
  312.         Console.WriteLine ("Simple decrement operation:");
  313.         for (int i = 50; i > 0; --i) {
  314.             Console.WriteLine ("{0}: {1}", i, h1);
  315.             --h1;
  316.         }
  317.  
  318.         Console.WriteLine ("Creation of new object using a string:");
  319.         HexaTriDecimalType h2 = new HexaTriDecimalType ("sdf", 5);
  320.         Console.WriteLine (h2);
  321.  
  322.         Console.WriteLine ("Demonstrates copy construction:");
  323.         HexaTriDecimalType h3 = new HexaTriDecimalType (h2);
  324.         Console.WriteLine (h3);
  325.  
  326.         Console.WriteLine ("Demonstrates comparison operation:");
  327.         HexaTriDecimalType h4 = new HexaTriDecimalType ("0ASD0");
  328.         Console.WriteLine (h4 == "000asd0");
  329.  
  330.         Console.WriteLine ("Demonstrates use of static method for incrementing a bare string:");
  331.         string s = "x";
  332.         s = HexaTriDecimalType.GetNextNumber (s);
  333.         for (int i = 0; i < 10; ++i) {
  334.             Console.WriteLine (s);
  335.             s = HexaTriDecimalType.GetNextNumber (s);
  336.         }
  337.  
  338.         Console.WriteLine ("Works well for fairly large strings too:");
  339.         string n = "AAAAAAAAAAAA";
  340.         for (int i = 0; i < 10; ++i) {
  341.             n = HexaTriDecimalType.GetNextNumber (n);
  342.             Console.WriteLine ("{0}", n);
  343.         }
  344.     }
  345. }

Output

Simple increment operation:
0: 0000000000
1: 0000000001
2: 0000000002
3: 0000000003
4: 0000000004
5: 0000000005
6: 0000000006
7: 0000000007
8: 0000000008
9: 0000000009
10: 000000000A
11: 000000000B
12: 000000000C
13: 000000000D
14: 000000000E
15: 000000000F
16: 000000000G
17: 000000000H
18: 000000000I
19: 000000000J
20: 000000000K
21: 000000000L
22: 000000000M
23: 000000000N
24: 000000000O
25: 000000000P
26: 000000000Q
27: 000000000R
28: 000000000S
29: 000000000T
30: 000000000U
31: 000000000V
32: 000000000W
33: 000000000X
34: 000000000Y
35: 000000000Z
36: 0000000010
37: 0000000011
38: 0000000012
39: 0000000013
40: 0000000014
41: 0000000015
42: 0000000016
43: 0000000017
44: 0000000018
45: 0000000019
46: 000000001A
47: 000000001B
48: 000000001C
49: 000000001D
50: 000000001E
Simple decrement operation:
49: 000000001D
48: 000000001C
47: 000000001B
46: 000000001A
45: 0000000019
44: 0000000018
43: 0000000017
42: 0000000016
41: 0000000015
40: 0000000014
39: 0000000013
38: 0000000012
37: 0000000011
36: 0000000010
35: 000000000Z
34: 000000000Y
33: 000000000X
32: 000000000W
31: 000000000V
30: 000000000U
29: 000000000T
28: 000000000S
27: 000000000R
26: 000000000Q
25: 000000000P
24: 000000000O
23: 000000000N
22: 000000000M
21: 000000000L
20: 000000000K
19: 000000000J
18: 000000000I
17: 000000000H
16: 000000000G
15: 000000000F
14: 000000000E
13: 000000000D
12: 000000000C
11: 000000000B
10: 000000000A
9: 0000000009
8: 0000000008
7: 0000000007
6: 0000000006
5: 0000000005
4: 0000000004
3: 0000000003
2: 0000000002
1: 0000000001
Creation of new object using a string:
00SDF
Demonstrates copy construction:
00SDF
Demonstrates comparison operation:
True
Demonstrates use of static method for incrementing a bare string:
Y
Z
10
11
12
13
14
15
16
17
Works well for fairly large strings too:
AAAAAAAAAAAB
AAAAAAAAAAAC
AAAAAAAAAAAD
AAAAAAAAAAAE
AAAAAAAAAAAF
AAAAAAAAAAAG
AAAAAAAAAAAH
AAAAAAAAAAAI
AAAAAAAAAAAJ
AAAAAAAAAAAK

Explanation

Additional notes

Known issues

The class in the listing above relies on strings rather than doing processing with actual numbers.

References

Wikipedia article on Base-36

See also

Further reading

External links

Author link

Najeeb (talk)

Discussions

Please do leave your comment. Thank you!

and

Nobody voted on this yet
 You need to enable JavaScript to vote
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox
Facebook Page
Twitter