Cambia.BaseN Documentation and Code Samples
By
Steve on
Monday, August 29, 2016
Updated
Friday, November 25, 2016
Viewed
11,662 times. (
2 times today.)
Create an Alphabet
An alphabet is the set of unique digits used to represent a number. The number of unique digits in your alphabet is the base, or radix.
For example, base-10 (decimal) uses an alphabet with ten digits 0123456789. Base-16 (hexadecimal) uses an alphabet with sixteen digits 0123456789ABCDEF.
Built-in:
Go here to learn more about the built-in alphabets. Up to base-62 they are exactly what you'd expect, after that things can get a touch wonky.
However, our Cambia95 standard alphabet reduces the wonk.
// You'll need the following using statement
using Cambia.BaseN;
// Use one of the static properties for special alphabets.
// This is likely all you'll every need.
BaseNAlphabet alpha = null;
alpha = BaseNAlphabet.Base2;
alpha = BaseNAlphabet.Base8;
alpha = BaseNAlphabet.Base10;
alpha = BaseNAlphabet.Base16;
alpha = BaseNAlphabet.Base36;
alpha = BaseNAlphabet.Base62;
alpha = BaseNAlphabet.Base64;
alpha = BaseNAlphabet.Base64_RFC4648;
alpha = BaseNAlphabet.Base64_RFC4648_Safe;
alpha = BaseNAlphabet.Base72;
alpha = BaseNAlphabet.Base72_Safe;
alpha = BaseNAlphabet.Base85;
alpha = BaseNAlphabet.Base85_Ascii85;
alpha = BaseNAlphabet.Base94;
alpha = BaseNAlphabet.Base95;
// Or get an alphabet of any length based on a built-in alphabet:
int radix = 53;
alpha = BaseNAlphabet.GetCambia95Alphabet(radix);
alpha = BaseNAlphabet.GetAscii85Alphabet(radix);
alpha = BaseNAlphabet.Get_Base64_Rfc4648_Alphabet(radix);
alpha = BaseNAlphabet.Get_Base64_Rfc4648_Safe_Alphabet(radix);
Custom:
// Create the standard base-10 alphabet
BaseNAlphabet a = new BaseNAlphabet("0123456789");
// Create a bizarre reverse base-10 alphabet
BaseNAlphabet a = new BaseNAlphabet("9876543210");
// Use the unique letters in your name to create a funky personalized alphabet
// In my case, it's a base-4 alphabet
BaseNAlphabet a = new BaseNAlphabet("STEV");
// Reset resets the class as if it were freshly instantiated
a.Reset("MARY");
// You can also instantiate with a character array
a = new BaseNAlphabet(new char[]{'M', 'i', 'c', 'h', 'a', 'e', 'l' });
// Or reset with one
a.Reset(new char[]{'s','a','b','i','n','e'});
Properties:
Alphabets are principally used as inputs to other operations, but they have a few readonly properties which are mainly used internally, but which might still be useful for you to know about.
// Radix -
int base = BaseNAlphabet.Base10.Radix; // base = 10
// SupportsNegative -
bool canDoNeg = BaseNAlphabet.Base10.SupportsNegative; // canDoNeg=true
// If an alphabet contains the minus sign, then it does not support negative numbers.
canDoNeg = BaseNAlphabet.Base64_RFC4648_Safe.SupportsNegative; // canDoNeg=false
canDoNeg = BaseNAlphabet.Base95.SupportsNegative; // canDoNeg=false
// ContainsWhitespace -
bool ws = BaseNAlphabet.Base10.ContainsWhiteSpace; // ws=false
// Base95 includes the space character as a digit so it does have whitespace
ws = BaseNAlphabet.Base95.ContainsWhiteSpace; // ws=true
The BaseConverter Class - Parsing and Converting
The BaseConverter class is a static object with all static methods to Parse, output and convert numbers in different bases.
Parse:
// If you want to use the BigInteger struct
// which allows integers of unlimited size you may
// need to include this namespace
using System.Numerics;
// Parse a binary number
// BaseConverter.Parse(string number, BaseNAlphabet sourceAlphabet);
// If a number can't fit in the specified output type, you'll get an OverflowException
BigInteger bi = BaseConverter.Parse("010100011010", BaseNAlphabet.Base2);
Int64 lg = BaseConverter.ParseToInt64("010100011010", BaseNAlphabet.Base2);
UInt64 ulg = BaseConverter.ParseToUInt64("010100011010", BaseNAlphabet.Base2);
Int32 i = BaseConverter.ParseToInt32("010100011010", BaseNAlphabet.Base2);
UInt32 ui = BaseConverter.ParseToUInt32("010100011010", BaseNAlphabet.Base2);
Guid g = BaseConverter.ParseToGuid("010100011010", BaseNAlphabet.Base2);
// Parse a hex number
bi = BaseConverter.Parse("A73FFB397", BaseNAlphabet.Base16);
lg = BaseConverter.ParseToInt64("A73FFB397", BaseNAlphabet.Base16);
ulg = BaseConverter.ParseToUInt64("A73FFB397", BaseNAlphabet.Base16);
i = BaseConverter.ParseToInt32("A73FFB397", BaseNAlphabet.Base16);
ui = BaseConverter.ParseToUInt32("A73FFB397", BaseNAlphabet.Base16);
g = BaseConverter.ParseToGuid("A73FFB397", BaseNAlphabet.Base16);
TryParse:
// TryParse a binary number
// bool result = BaseConverter.TryParse(string number, BaseNAlphabet sourceAlphabet, out T num);
bool result = false;
BigInteger bi = new BigInteger();
result = BaseConverter.TryParse("010100011010", BaseNAlphabet.Base2, out bi);
long lg = 0;
result = BaseConverter.TryParse("010100011010", BaseNAlphabet.Base2, out lg);
ulong ulg = 0;
result = BaseConverter.TryParse("010100011010", BaseNAlphabet.Base2, out ulg);
int i = 0;
result = BaseConverter.TryParse("010100011010", BaseNAlphabet.Base2, out i);
uint ui = 0;
result = BaseConverter.TryParse("010100011010", BaseNAlphabet.Base2, out ui);
Guid g = Guid.Empty;
result = BaseConverter.TryParse("010100011010", BaseNAlphabet.Base2, out g);
ToBaseN:
// Transform a number to base-n
// string output = BaseConverter.ToBaseN(T sourceNumber, BaseNAlphabet outputAlphabet);
// T=BigInteger, Guid, Int64, UInt64, Int32, UInt32
BigInteger bi = new BigInteger(1000);
string output = BaseConverter.ToBaseN(bi, BaseNAlphabet.Base2); // output=1111101000
output = BaseConverter.ToBaseN(bi, BaseNAlphabet.Base16); // output=3E8
output = BaseConverter.ToBaseN(bi, BaseNAlphabet.Base62); // output=G8
long lg = 1000;
output = BaseConverter.ToBaseN(lg, BaseNAlphabet.Base2); // output=1111101000
output = BaseConverter.ToBaseN(lg, BaseNAlphabet.Base16); // output=3E8
output = BaseConverter.ToBaseN(lg, BaseNAlphabet.Base62); // output=G8
ulong ulg = 1000;
output = BaseConverter.ToBaseN(ulg, BaseNAlphabet.Base2); // output=1111101000
output = BaseConverter.ToBaseN(ulg, BaseNAlphabet.Base16); // output=3E8
output = BaseConverter.ToBaseN(ulg, BaseNAlphabet.Base62); // output=G8
int i = 1000;
output = BaseConverter.ToBaseN(i, BaseNAlphabet.Base2); // output=1111101000
output = BaseConverter.ToBaseN(i, BaseNAlphabet.Base16); // output=3E8
output = BaseConverter.ToBaseN(i, BaseNAlphabet.Base62); // output=G8
uint ui = 1000;
output = BaseConverter.ToBaseN(ui, BaseNAlphabet.Base2); // output=1111101000
output = BaseConverter.ToBaseN(ui, BaseNAlphabet.Base16); // output=3E8
output = BaseConverter.ToBaseN(ui, BaseNAlphabet.Base62); // output=G8
Guid g = new Guid("00000000-0000-0000-0000-0000000003E8");
output = BaseConverter.ToBaseN(g, BaseNAlphabet.Base2); // output=1111101000
output = BaseConverter.ToBaseN(g, BaseNAlphabet.Base16); // output=3E8
output = BaseConverter.ToBaseN(g, BaseNAlphabet.Base62); // output=G8
Convert:
// Convert a number directly from base-n to base-m
// string output = BaseConverterConvert(string num, BaseNAlphabet sourceA, BaseNAlphabet, outputA);
string output = BaseConverter.Convert("1000", BaseNAlphabet.Base10, BaseNAlphabet.Base36); // output=RS
// Convert a Guid to Base72.
// This is obviously not the easy way to do this. See the section on extension methods.
Guid g = new Guid("8C55203D-5DCF-4CC3-828C-A841F5EE5668");
string s = BaseConverter.Convert(g.ToString().ToUpper().Replace("-", ""), BaseNAlphabet.Base16, BaseNAlphabet.Base72);
Extension Methods
In order to make the use of extension methods you'll just need the using directive:
using Cambia.BaseN;
Then the following types:
- BigInteger (may need a reference to System.Numerics for this type)
- Int64
- UInt64
- Int32
- UInt32
- Guid
will all support the following methods:
Parse:
// Signature:
// num.Parse(string sourceNum, BaseNAlphabet sourceA);
// Parses "1111101000" as a base-2 number and returns the value.
BigInteger bi = 0;
BigInteger bi2 = bi.Parse("1111101000", BaseNAlphabet.Base2); // bi=0, bi2=1000
bi = bi.Parse("1111101000", BaseNAlphabet.Base2); // bi=1000
// Behavior is similar for the other supported types:
// Int64, UInt64, Int32, UInt32, Guid
TryParse:
// Signature:
// bool success = num.TryParse(string sourceNum, BaseNAlphabet sourceA, out T output);
// where T is one of the supported types.
// Attempts to parse "1111101000" as a base-2 number and returns that value in the out parameter.
// If successful, return value is true. NOTE: Does not change the value of bi unless bi is
// itself the out parameter passed into the method as follows
bool result = bi.TryParse("1111101000", BaseNAlphabet.Base2, out bi); // if success, bi=1000
// Parse the value into a different variable (bi2).
bi = 0;
result = bi.TryParse("1111101000", BaseNAlphabet.Base2, out bi2); // if success, bi=0, bi2=1000
// Behavior is similar for the other supported types:
// Int64, UInt64, Int32, UInt32, Guid
ToBaseN:
// Signature:
// string output = num.ToBaseN(BaseNAlphabet targetAlphabet);
// Convert a type to a base-n representation
bi = 1000;
string num = bi.ToBaseN(BaseNAlphabet.Base2); // num=1111101000
// Behavior is similar for the other supported types:
// Int64, UInt64, Int32, UInt32, Guid
Additional Examples
Quick Math:
// Add two binary numbers and represent them as a hex number
int b1 = 0;
int sum = b1.Parse("1000101011001111", BaseNAlphabet.Base2)
+ b1.Parse("111010100110000", BaseNAlphabet.Base2);
string hexNum = sum.ToBaseN(BaseNAlphabet.Base16); // hexNum = FFFF
Compress GUID for URL:
Even though GUIDs in URLs can be extremely useful, they're ugly. At 36 characters they take up a lot
of real estate.
https://www.domain.com/8C55203D-5DCF-4CC3-828C-A841F5EE5668
This base-36 representation is less ugly (not much, but a little)
https://www.domain.com/8B377QEPEYB7BPRC75XTAE9NS
This base-62 representation is arguably not less ugly at all, but it's shorter
https://www.domain.com/4GnpMWOg6CP4Fg5Vfqu2Rs
Finally, this base-72 representation is pretty ugly, but it's safe for a URL and it's one character shorter.
https://www.domain.com/DMB!Ii;,n+Yb5l16c!uT!
It seems we have a sweet spot in the base-36 to base-62 range.
// Shortening your URL by converting your Guid to a different base
// and then back again is super easy
Guid g = new Guid("8C55203D-5DCF-4CC3-828C-A841F5EE5668");
// base-36
string shortGuid = g.ToBaseN(BaseNAlphabet.Base36);
g = g.Parse(shortGuid, BaseNAlphabet.Base36);
// base-62
shortGuid = g.ToBaseN(BaseNAlphabet.Base62);
g = g.Parse(shortGuid, BaseNAlphabet.Base62);
// base-72 safe
shortGuid = g.ToBaseN(BaseNAlphabet.Base72_Safe);
g = g.Parse(shortGuid, BaseNAlphabet.Base72_Safe);