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

2 Answers 2

9
\$\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
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\$
5
  • \$\begingroup\$ This code doesn't even compile. \$\endgroup\$
    – Dmitry
    May 13, 2015 at 12:24
  • \$\begingroup\$ What errors are it throwing? \$\endgroup\$
    – somebody
    May 13, 2015 at 12:31
  • \$\begingroup\$ Try it yourself and see. \$\endgroup\$
    – Dmitry
    May 13, 2015 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, 2015 at 12:47
  • \$\begingroup\$ Fixed, and edited. \$\endgroup\$
    – somebody
    May 14, 2015 at 10:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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