10
\$\begingroup\$

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.

\$\endgroup\$
  • 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 May 12 '15 at 15:59
  • 1
    \$\begingroup\$ Yes, can be like Excel \$\endgroup\$ – Jonny Piazzi May 12 '15 at 16:13
8
\$\begingroup\$

You could slightly simplify the code as follows:

  • Reduce the number of variables.
  • Use the LinkedList<T> (and the AddFirst method) instead of the List<T> to eliminate reversion of array.
    Alternatively you can use the List<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());
}
\$\endgroup\$
0
\$\begingroup\$

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());
}
\$\endgroup\$
  • \$\begingroup\$ This code doesn't even compile. \$\endgroup\$ – Dmitry May 13 '15 at 12:24
  • \$\begingroup\$ What errors are it throwing? \$\endgroup\$ – somebody May 13 '15 at 12:31
  • \$\begingroup\$ Try it yourself and see. \$\endgroup\$ – Dmitry May 13 '15 at 12:36
  • \$\begingroup\$ And please perform some tests before posting. For instance, make sure that this code returns ZYZ for 18252. \$\endgroup\$ – Dmitry May 13 '15 at 12:47
  • \$\begingroup\$ Fixed, and edited. \$\endgroup\$ – somebody May 14 '15 at 10:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.