One of the things that is great about integers and longs is that they are easy to remember. However, when using this as identifiers that a human should be able to type in, they leave a lot to be desired. A integer in the billion range requires a user to enter 10 digits correctly. That’s hard to read, hard to keep your place, etc. There is a solution to this issue: represent the data using a radix other than 10. For English speakers, a radix of 36 is easily readable and maximizes the density while allowing for case insensitivity (no one wants to remember if they should type z or Z!).
Consider this, the value for int.MaxValue is written out as:
2147483647
As base 36, it is
zik0zj
6 characters instead of 10. Nice!
To do this, I wrote a simple function that converts a long (64 bits!) to any radix between 2 and 36. This is a basic first or second semester CS problem, I know. Still, this code is handy to have when you need it for converting numbers into something a person can type in:
static string ConvertToString(long value, int toBase) { if (toBase < 2 || toBase > 36) { throw new ArgumentOutOfRangeException("toBase", "Must be in the range of [2..36]"); } var values = new List<char>(); for (var val = '0'; val <= '9'; ++val) { values.Add(val); } for (var val = 'a'; val <= 'z'; ++val) { values.Add(val); } var builder = new StringBuilder(); bool isNegative = false; if (value < 0) { value = -value; isNegative = true; } do { long index = value%toBase; builder.Insert(0, values[(int)index]); value = value/toBase; } while (value != 0); if (isNegative) { builder.Insert(0, '-'); } return builder.Length == 0 ? "0" : builder.ToString(); }
And, to go the other way:
static long ConvertToLong(string input, int fromBase) { if (fromBase < 2 || fromBase > 36) { throw new ArgumentOutOfRangeException("fromBase", "Must be in the range of [2..36]"); } if (string.IsNullOrEmpty(input)) return 0; input = input.Trim(); var values = new List<char>(); for (var val = '0'; val <= '9'; ++val) { values.Add(val); } for (var val = 'a'; val <= 'z'; ++val) { values.Add(val); } var builder = new StringBuilder(); bool isNegative = false; int startIndex = 0; if (input[0] == '-') { isNegative = true; ++startIndex; } long retval = 0; for(int index = startIndex; index < input.Length; ++index) { retval *= fromBase; bool found = false; for (int number = 0; number < fromBase; ++number) { if (input[index] == values[number]) { retval += number; found = true; } } if (!found) break; } if (isNegative) { retval = -retval; } return retval; }