I needed to create a simple method that converts numbers in Base 26 (string
) using, as expected, letters from a to z.
But that's not all, this Base 26 needs to be One Based. Which means that there is no representation for zero absolute value and there is a representation for 26 absolute value. Let me show a example:
In Base 26 Zero Based the number 18252 will be represented like:
$$ (18252)_{10} = (BBAA)_{26} $$
where B == 1
and A == 0
. But as an One Based I need to get:
$$ (18252)_{10} = (ZYZ)_{26} $$
where Y == 25
and Z == 26
.
So I came up with this snippet:
var array = new List<int>();
var div = myNumber;
var getOne = 0;
while (div > 26)
{
var value = div % 26;
value -= getOne;
if (value <= 0)
{
value += 26;
getOne = 1;
}
else
{
getOne = 0;
}
array.Add(value);
div = div / 26;
}
div -= getOne;
if (div > 0) array.Add(div);
var letters = array.Select(s => (char)('A' + s - 1)).Reverse().ToArray();
return new string(letters);
Now I wonder if there is a better way write this.
-
2\$\begingroup\$ It looks like you are trying to get an excel column name from a number e.g. 1 => A, 2 => B, ... 26 => Z, 27 => AA, 28 => AB. Is this correct? If so, are you happy with a solution that works as far as 16384 (the max number of columns in an Excel spreadsheet)? \$\endgroup\$AlanT– AlanT2015年05月12日 15:59:28 +00:00Commented May 12, 2015 at 15:59
-
1\$\begingroup\$ Yes, can be like Excel \$\endgroup\$Jonny Piazzi– Jonny Piazzi2015年05月12日 16:13:34 +00:00Commented May 12, 2015 at 16:13
2 Answers 2
You could slightly simplify the code as follows:
- Reduce the number of variables.
- Use the
LinkedList<T>
(and theAddFirst
method) instead of theList<T>
to eliminate reversion of array.
Alternatively you can use theList<T>.Insert
method to achieve the same result.
The code:
private static string ToBase26(int myNumber)
{
var array = new LinkedList<int>();
while (myNumber > 26)
{
int value = myNumber % 26;
if (value == 0)
{
myNumber = myNumber / 26 - 1;
array.AddFirst(26);
}
else
{
myNumber /= 26;
array.AddFirst(value);
}
}
if (myNumber > 0)
{
array.AddFirst(myNumber);
}
return new string(array.Select(s => (char)('A' + s - 1)).ToArray());
}
You could reduce the number of variables, and use LinkedList<T>
method to eliminate reversion, like this:
private static string ToBase26(int number)
{
var list = new LinkedList<int>();
list.AddFirst((number - 1) % 26);
while ((number = --number / 26 - 1) > 0) list.AddFirst(number % 26);
return new string(list.Select(s => (char)(s + 65)).ToArray());
}
-
\$\begingroup\$ This code doesn't even compile. \$\endgroup\$Dmitry– Dmitry2015年05月13日 12:24:38 +00:00Commented May 13, 2015 at 12:24
-
\$\begingroup\$ What errors are it throwing? \$\endgroup\$somebody– somebody2015年05月13日 12:31:18 +00:00Commented May 13, 2015 at 12:31
-
\$\begingroup\$ Try it yourself and see. \$\endgroup\$Dmitry– Dmitry2015年05月13日 12:36:24 +00:00Commented May 13, 2015 at 12:36
-
\$\begingroup\$ And please perform some tests before posting. For instance, make sure that this code returns
ZYZ
for18252
. \$\endgroup\$Dmitry– Dmitry2015年05月13日 12:47:34 +00:00Commented May 13, 2015 at 12:47 -
\$\begingroup\$ Fixed, and edited. \$\endgroup\$somebody– somebody2015年05月14日 10:57:31 +00:00Commented May 14, 2015 at 10:57