Take the 2-minute tour ×

I have a five-character String and I want to use those five characters as an ASCII-encoded (printable) number. The simplest way to achieve this is to use

Long.toString(number, Character.MAX_RADIX);

This will give me numbers from "0" to "zzzzz". Unfortunately Long.toString(int, int) only supports lower-case letters, no upper-case letters. This means that the max radix is 36 and the highest number I can encode is 36^5 - 1 = 60 466 175. If I could use both lower and upper-case letters, I'd get a max radix of 62 and the highest encodable number is 62^5 - 1 = 916 132 831.

Apart from copying Long's source code and extending the possible digits, is there any other place I should look into, first, where this is already implemented?

share|improve this question
You might want to look for Base64 encoders and decoders (e.g., commons.apache.org/codec/apidocs/org/apache/commons/codec/…), which use two additional symbols for encoding. –  subsub Apr 27 '11 at 11:47
@subsub: see WhiteFang's answer –  Lukas Eder Apr 27 '11 at 11:48
add comment

2 Answers

up vote 1 down vote accepted

You don't specify whether or not the characters need to be printable ASCII:

  • If they do, then you can go to 95^5. There are 95 printable ASCII characters from space (SP) to tilde (~).

  • If they don't, then you can go to 128^5 == 2^35.

Either way, the algorithm for doing the conversion is straightforward, and is simpler than an extension to Long.toString(...). (You presumably don't have to worry about signs, range errors, or holes in the character <-> digit mapping. It would be easier to code this from scratch.)

However, I'm not aware of any existing implementation of extended radix numbers.

share|improve this answer
They need to be "printable". I'll update the question, thanks. Apart from [0-9a-zA-Z] some special characters would be OK, too (such as /, -, _, etc) –  Lukas Eder Apr 27 '11 at 12:19
thanks for the update. I know it's straightforward. I can copy it from java.lang.Long. I was just wondering if I overlooked something where Character.MAX_RADIX is not the limit... –  Lukas Eder Apr 27 '11 at 12:23
add comment

If you're willing to go two characters beyond alphanumeric you could use Base64 encoding.

Using Base64 from Apache Commons Codec you could get 1073741824 possible values like this:

byte bytes[] = new byte[4];
bytes[0] = (byte) ((value >> 24) & 0xFF);
bytes[1] = (byte) ((value >> 16) & 0xFF);
bytes[2] = (byte) ((value >> 8) & 0xFF);
bytes[3] = (byte) (value & 0xFF);
String encoded = Base64.encodeBase64String(bytes).substring(1, 6);
share|improve this answer
Good idea. But the trailing = and == won't use up extra space? Apart from that, I didn't consider it, because the transformation goes from byte[] to String, not from Number to String. But I could handle the extra "encoding" from Number to byte[] –  Lukas Eder Apr 27 '11 at 11:49
You could avoid the trailing = by using 3 bytes of an int. That would give you an even 24 bits to be encoded into 4 characters. –  WhiteFang34 Apr 27 '11 at 11:55
3 bytes is not enough: 256^3 - 1 = 16 777 215, which is less than my original solution where I get 60 466 175 encodable values –  Lukas Eder Apr 27 '11 at 11:57
Oops, somehow the magnitude of your number didn't register and I blindly turned 5 characters into 4 for you :) I updated the answer with a way to get more. For 4 bytes you can safely trim the trailing ==. And then also remove the first character that'll be the bits from the int that just won't fit into your 5 characters. –  WhiteFang34 Apr 27 '11 at 12:03
Thanks for your effort. That sounds more complicated to me than copying Long.toString(int, int) and adding a couple of allowed digits to the algorithm. :-) Besides, I don't understand the base64 algorithm well enough to be sure that trimming will not accidentally create "collisions", i.e. several numbers being encoded to the same value, which would be fatal in my case. –  Lukas Eder Apr 27 '11 at 12:10
add comment

Your Answer


