3

可能重复:
将 21 个字母数字字符压缩为 16 个字节

我有8个号码

有没有办法将其转换为长度为 4 的字符串?

例如:

输入12345678

输出AB2D

转换应该能够完全转换回来。

我试图将它转换为 32 Hex,但它仍然有 5 个数字,我不能0 1 O I在最终字符串中使用。有什么好的建议吗?顺便说一句,只能使用大写字母。

4

2 回答 2

13

它归结为数学。如果您需要能够表示 10^8 个可能的数字并且需要使用 4 个符号,则每个符号必须允许 100 个不同的值。10^8^(1/4)您可以使用 8 位字节执行此操作,但您的要求only upper case letters could be used.表明您的选择非常有限。您必须确定可以使用的 100 个字母,或者您必须对可以使用的数字范围做出假设。

顺便说一句:如果您可以使用非 ASCII 大写字符,则没有问题。;)

有 26 个大写 ASCII 字符,30 个介于 128 和 255 之间的大写字符以及 10 个数字,因此您也必须使用 34 个符号。如果可以使用 Unicode,则有 1898 个大写和数字 Unicode 字符。

(char) 32和之间有 163 个非小写字符(char) 255,如果你能使用其中的大部分,你就可以做到。


手工挑选的可能字符列表将是更好的选择,但这是一个示例。

static final char[] ENCODE = new char[100];

static {
    int x = 0;
    for (char i = ' ' + 1; i < 256 && x < 100; i++)
        if (!Character.isLowerCase(i) && !Character.isWhitespace(i))
            ENCODE[x++] = i;
    assert x == ENCODE.length;
}

public static char[] encode(int n) {
    assert n >= 0 && n < 100000000;
    char[] ret = new char[4];
    for (int i = ret.length - 1; i >= 0; i--) {
        ret[i] = ENCODE[n % 100];
        n /= 100;
    }
    return ret;
}

public static int decode(char[] chars) {
    int n = 0;
    for (char ch : chars) {
        int x = Arrays.binarySearch(ENCODE, ch);
        assert x >= 0;
        n = n * 100 + x;
    }
    return n;
}

public static void main(String... args) {
    char[] chars = encode(12345678);
    System.out.println("Encoded: " + new String(chars));
    int n = decode(chars);
    System.out.println("Dencoded: " + n);
}

使用此字体不可打印的字符打印:(

Encoded: -CY
Dencoded: 12345678
于 2012-10-16T09:44:30.333 回答
1

不,八位数字代表太多的组合。每个十进制数字都必须用单个符号表示,才能使整数成为长度为 4 的字符串。这意味着您需要使用 100 个符号。正如您所说,十六进制没有足够的字符,尽管它比十进制多。如果您不能使用小写字母,我假设也不允许使用标点符号。在这种情况下,您将没有足够的符号。

于 2012-10-16T09:44:42.170 回答