43

Is there a nicer way of converting a number to its alphabetic equivalent than this?

private String getCharForNumber(int i) {
    char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    if (i > 25) {
        return null;
    }
    return Character.toString(alphabet[i]);
}

Maybe something than can deal with numbers greater than 26 more elegantly too?

Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
edwardmlyte
  • 15,937
  • 23
  • 58
  • 83
  • What value do you expect for a number greater than 26? – adarshr May 30 '12 at 09:08
  • What is the use case for this and the numbers greater than 25? Perhaps there is another way. – Ewald May 30 '12 at 09:08
  • I don't need numbers greater than 26. At the moment only 10 results are displayed at a time, but they may want to increase to 20. Thought it looked neater to just include the entire alphabet. I wasnt sure if there's some apache commons library can do this in one line (I did google around). – edwardmlyte May 30 '12 at 09:12

17 Answers17

88

Just make use of the ASCII representation.

private String getCharForNumber(int i) {
    return i > 0 && i < 27 ? String.valueOf((char)(i + 64)) : null;
}

Note: This assumes that i is between 1 and 26 inclusive.

You'll have to change the condition to i > -1 && i < 26 and the increment to 65 if you want i to be zero-based.

Here is the full ASCII table, in case you need to refer to:


enter image description here


Edit:

As some folks suggested here, it's much more readable to directly use the character 'A' instead of its ASCII code.

private String getCharForNumber(int i) {
    return i > 0 && i < 27 ? String.valueOf((char)(i + 'A' - 1)) : null;
}
adarshr
  • 61,315
  • 23
  • 138
  • 167
44

Rather than giving an error or some sentinel value (e.g. '?') for inputs outside of 0-25, I sometimes find it useful to have a well-defined string for all integers. I like to use the following:

   0 ->    A
   1 ->    B
   2 ->    C
 ...
  25 ->    Z
  26 ->   AA
  27 ->   AB
  28 ->   AC
 ...
 701 ->   ZZ
 702 ->  AAA
 ...

This can be extended to negatives as well:

  -1 ->   -A
  -2 ->   -B
  -3 ->   -C
 ...
 -26 ->   -Z
 -27 ->  -AA
 ...

Java Code:

public static String toAlphabetic(int i) {
    if( i<0 ) {
        return "-"+toAlphabetic(-i-1);
    }

    int quot = i/26;
    int rem = i%26;
    char letter = (char)((int)'A' + rem);
    if( quot == 0 ) {
        return ""+letter;
    } else {
        return toAlphabetic(quot-1) + letter;
    }
}

Python code, including the ability to use alphanumeric (base 36) or case-sensitive (base 62) alphabets:

def to_alphabetic(i,base=26):
    if base < 0 or 62 < base:
        raise ValueError("Invalid base")

    if i < 0:
        return '-'+to_alphabetic(-i-1)

    quot = int(i)/base
    rem = i%base
    if rem < 26:
        letter = chr( ord("A") + rem)
    elif rem < 36:
        letter = str( rem-26)
    else:
        letter = chr( ord("a") + rem - 36)
    if quot == 0:
        return letter
    else:
        return to_alphabetic(quot-1,base) + letter
Quantum7
  • 3,165
  • 3
  • 34
  • 45
  • How do I go back from alphabetic to number ? – KenobiBastila Oct 25 '18 at 14:42
  • I don't have time atm to write the code, but you would basically pop a character off the left of the string, convert to a number 0-25, then if more letters remain multiply by 26 and recurse. This is just a base-26 encoding, so the math isn't tricky. – Quantum7 Oct 27 '18 at 15:07
  • I will post a question in a few days with a bounty. I would love if you could write the code :D – KenobiBastila Oct 27 '18 at 17:46
5

I would return a character char instead of a string.

public static char getChar(int i) {
    return i<0 || i>25 ? '?' : (char)('A' + i);
}

Note: when the character decoder doesn't recognise a character it returns ?

I would use 'A' or 'a' instead of looking up ASCII codes.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
4

if you define a/A as 0

char res;
if (i>25 || i<0){
    res = null;
}
    res = (i) + 65
}
return res;

65 for captitals; 97 for non captitals

Baptiste Gousset
  • 251
  • 2
  • 16
4

Personally, I prefer

return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".substring(i, i+1);

which shares the backing char[]. Alternately, I think the next-most-readable approach is

return Character.toString((char) (i + 'A'));

which doesn't depend on remembering ASCII tables. It doesn't do validation, but if you want to, I'd prefer to write

char c = (char) (i + 'A');
return Character.isUpperCase(c) ? Character.toString(c) : null;

just to make it obvious that you're checking that it's an alphabetic character.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
2
public static String abcBase36(int i) {
    char[] ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    int quot = i / 36;
    int rem = i % 36;

    char letter = ALPHABET[rem];
    if (quot == 0) {
        return "" + letter;
    } else {
        return abcBase36(quot - 1) + letter;
    }
}
Samuel Philipp
  • 10,631
  • 12
  • 36
  • 56
Sotona
  • 158
  • 11
2

Getting the alphabetical value from an int can be simply done with:

(char)('@' + i)
slfan
  • 8,950
  • 115
  • 65
  • 78
riad
  • 21
  • 1
1

You can convert the input to base 26 (Hexavigesimal) and convert each "digit" back to base 10 individually and apply the ASCII mapping. Since A is mapped to 0, you will get results A, B, C,..., Y, Z, BA, BB, BC,...etc, which may or may not be desirable depending on your requirements for input values > 26, since it may be natural to think AA comes after Z.

public static String getCharForNumber(int i){

    // return null for bad input
    if(i < 0){
        return null;
    }

    // convert to base 26
    String s = Integer.toString(i, 26);

    char[] characters = s.toCharArray();

    String result = "";
    for(char c : characters){
        // convert the base 26 character back to a base 10 integer
        int x = Integer.parseInt(Character.valueOf(c).toString(), 26);
        // append the ASCII value to the result
        result += String.valueOf((char)(x + 'A'));          
    }

    return result;
}
klb77
  • 11
  • 1
  • This is a very elegant solution that actually uses math. Unfortunately, by choosing to represent A with zero, B with 1, etc., there is no number that maps to AA after Z (25). :-( It must go from Z to BA. – Tihamer Aug 28 '19 at 18:09
1
public static string IntToLetters(int value)
{
string result = string.Empty;
while (--value >= 0)
{
    result = (char)('A' + value % 26 ) + result;
    value /= 26;
}
return result;
}

To meet the requirement of A being 1 instead of 0, I've added -- to the while loop condition, and removed the value-- from the end of the loop, if anyone wants this to be 0 for their own purposes, you can reverse the changes, or simply add value++; at the beginning of the entire method.

0

You can try like this:

private String getCharForNumber(int i) {
    CharSequence css = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    if (i > 25) {
        return null;
    }
    return css.charAt(i) + "";
}
Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
UVM
  • 9,776
  • 6
  • 41
  • 66
  • Any particular reason for using `CharSequence` instead of plain old `String`? – adarshr May 30 '12 at 09:20
  • I think it is internally uses char array which is faster in string operation. – UVM May 30 '12 at 09:27
  • So does `String`! Hope you realise that `String` extends `CharSequence`. – adarshr May 30 '12 at 09:28
  • Yes. you can reduce the memory footprint.http://stackoverflow.com/questions/8445311/choosing-between-charsequence-and-string-for-an-api – UVM May 30 '12 at 09:32
  • I don't fully agree. Even if it were to, it would be pointless in this instance. Besides, you're converting the whole thing to a `String` before returning anyway. – adarshr May 30 '12 at 09:38
  • However, that operation is always required because he need String as return type.Let him change it to char.So no probs. – UVM May 30 '12 at 09:43
0

Another variant:

private String getCharForNumber(int i) {
    if (i > 25 || i < 0) {
        return null;
    }
    return new Character((char) (i + 65)).toString();
}
simon
  • 12,666
  • 26
  • 78
  • 113
0

This isn't exactly an answer, but some useful/related code I made. When you run it and enter any character in the command line it returns getNumericValue(char) ... which doesn't seem to be the same as the ASCII table so be aware. Anyways, not a direct answer to your question but hopefully helpful:

import java.lang.*;
import java.util.*;
/* charVal.java
         */

//infinite loops. whenever you type in a character gives you value of 
//getNumericValue(char)
//
//ctrl+c to exit



public class charVal {
   public static void main(String[] args) {
     Scanner inPut = new Scanner(System.in);
     for(;;){
       char c = inPut.next().charAt(0);
       System.out.printf("\n %s = %d \n", c, Character.getNumericValue(c));
     }
    }
}
Robert
  • 1
0

Another approach starting from 0 and returning a String

public static String getCharForNumber(int i) {
    return i < 0 || i > 25 ? "?" : String.valueOf((char) ('A' + i));
}
Gnzlt
  • 4,383
  • 2
  • 22
  • 24
0
public static void main(String[] args)
 {
     int rem,n=702,quo;
     String s=" ";
     while(n>0)
     {
         rem=(n-1)%26;
         quo=(n-1)/26;
         s=(char)(rem+97)+s;
         if(quo==1)
         {
            s=(char)(97)+s;
            break;
         }
         else
         n=(n-1)/26;
     }
     System.out.print(s);
 }
}
////We can also write the code like the below one. There is no much difference but it may help to understand the concept for some people.


public static void main(String[] args)
 {
     int rem,n=52,quo;
     String s=" ";
     while(n>0)
     {
         rem=n%26;
         quo=n/26;
         if(rem==0)
             rem=26;
         s=(char)(rem+96)+s;
         if((quo==1 || quo==0) && n>26)
         {
             n=n/26;
            s=(char)(n+96)+s;
            break;
         }
         else
             n=n/26-1; 
     }
     System.out.print(s);
 }
0
for(int i=0;i<ar.length();i++) {
            char ch = ar.charAt(i);
                    System.out.println((char)(ch+16));;
        }
  • Please [include an explanation for your code](https://meta.stackoverflow.com/q/392712/5698098), as that helps to improve the quality of your post. Given that there are already plenty of other answers it'd be interesting if you'd explain the merits of your answer here. – Ivo Mori Sep 27 '20 at 11:21
0

The accepted answer best describes the solution. Nevertheless, it does not handle the case when you want to keep numbering over the value 27 like aa, ab, ...az, aaa, aab.... For doing so I achieved with the following:

protected String getAlphaNumber(int intValue) {
    if (intValue == 0) {
        return "";
    }
    intValue = Math.abs(intValue);
    String prefix = "";
    int charPosition = intValue % 26;
    int blocks = intValue / 26;
    if (charPosition == 0) { //the last letter, "z" (26)
        blocks--;
        charPosition = 26;
    }
    for (int i = 0; i < blocks; i++) {
        prefix += "a";
    }
    return prefix + ((char) (charPosition + 96)); // "a"-"z" chars are located in the 97-122 indexes of the ASCII table, so shift all 96 positions.
}
Ermal
  • 441
  • 5
  • 19
0

import java.util.*;

class Integer2Letter

{

     void main()

     {

         Scanner ob=new Scanner(System.in);

         int n;

         System.out.println("Enter an Integer");

         n=ob.nextInt();//INPUT IN INTEGER FORMAT

         if(n>0 && n<27)//RANGE CHECK

         {

             char ch= (char)(n+64);//IF N=1 THAN 64+1=65 WHICH EQUAL TO THE ASCII VALUE        OF 'A' 

             System.out.println("the corresponding letter is="+ch);

         }

         else

         {

             System.out.println("Please enter the correct range");

         }

     }

}