HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Converting base-10 numbers into base-26 letters

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
intonumbersbaseconvertingletters

Problem

I'm writing something that basically takes a bunch of files and renames them into a nice format, such as pic_000.jpeg, pic_001.jpeg, etc. One of the options is to write the incrementation as letters, e.g. pic_aaa.jpeg, pic_aab.jpeg, etc. Also, is they are converting a set of pic_000s into a set of pic_aaas, then there's also an option to preserve the order of increments. In other words, if you deleted pic_000 through pic_117, then the pic_aaa set would start at pic_aen, not pic_aaa. It's a little weird, but I'm just trying to give the user lot of options so they can do whatever they want.

I suppose there are two different types of output for a base-10 to base-26 function such as this:

-
without a fixed-length result, e.g.: A, B, ... , Z, AA, AB, ... ZZ, AAA (notice that A is representing a 1 when it is the leading letter and the result is more than one letter in length, else it is representing a 0)

-
with a fixed-length result, e.g. AAA, AAB, ... , ZZY, ZZZ (A will always represent a zero, here)

Again, I've chosen to write it both ways and let the user decide what they want. With (2), you just have to count how many input numbers there are (the numbers that we're converting in the first place) and then use an appropriately-sized result. Obviously two characters (AA, AB, etc.) isn't enough to represent a million different numbers, so you'd have see if three letters could do it, then four, and so on. (To make this easier, you can just do resultLength = ceil(log(inputNumber)/log(26)) (not vb6 code, but you get the idea) I haven't written (2) yet, but I assume it will be pretty easy.

Number 1, though, proved to be a bit of a doozy since A-Z can represent 0-25 in some places and 1-26 in others. If A is 0, then Z is 25, but unless you want to use BA for 26, skipping A_, then you have to let A be equal to 1 where it is a leading character (e.g. AA, AB, etc.) when the result is not 1 character long (i.e. for the result of A, A is 0

Solution

First Point:

For multiple If/Else blocks, I prefer to use Select Case. I would just do this out of habit, though your check is small enough that it may not matter too much.

Also, this may be trickier, given that something falling into the first case looks like it would also fall into the other two. However, unlike other languages, there is no break required, and the Select block ends at the first case it comes to (like the If/Else would have).

Select Case input

Case Is < 26 ^ 1:
    resultLength = 1
Case Is < (27 * (26 ^ 1) - 1): 'ZZ represents (27*26) -1
    resultLength = 2
Case Is < (27 * (26 ^ 2) - 1): 'ZZ represents (27*26^2) -1
    resultLength = 3
End Select


Second Point:

I know I'm not doing much in the way of efficiency (more just style, I think), but here's another. Regarding:

If (i = Index) And (Index > 1) And Int(asLong / 26 ^ (i)) = 1 Then
    j = 26 ^ i
    asLong = asLong - 26 ^ (i - 1)
Else
    j = 26 ^ i
End If


Since you assign j = 26 ^ i in both cases, why not just assign it before the If?

j = 26 ^ i

If (i = Index) And (Index > 1) And Int(asLong / 26 ^ (i)) = 1 Then
    asLong = asLong - 26 ^ (i - 1)
End If


Sorry for not getting this all out at once. I'll continue to pick apart as I have time and add to this answer as needed...

Code Snippets

Select Case input

Case Is < 26 ^ 1:
    resultLength = 1
Case Is < (27 * (26 ^ 1) - 1): 'ZZ represents (27*26) -1
    resultLength = 2
Case Is < (27 * (26 ^ 2) - 1): 'ZZ represents (27*26^2) -1
    resultLength = 3
End Select
If (i = Index) And (Index > 1) And Int(asLong / 26 ^ (i)) = 1 Then
    j = 26 ^ i
    asLong = asLong - 26 ^ (i - 1)
Else
    j = 26 ^ i
End If
j = 26 ^ i

If (i = Index) And (Index > 1) And Int(asLong / 26 ^ (i)) = 1 Then
    asLong = asLong - 26 ^ (i - 1)
End If

Context

StackExchange Code Review Q#13480, answer score: 2

Revisions (0)

No revisions yet.