表示长期至少数量的字符

时间:2014-12-19 03:52:11

标签: java scala

我需要用最短的字符串表示非常大和小的数字。这些数字是未签名的。我已经尝试过直接的Base64编码,但是对于一些较小的数字,编码的字符串比仅将数字存储为字符串更长。在URL最安全的情况下,以最短的字符串最佳地存储非常大或短的数字的最佳方法是什么?

3 个答案:

答案 0 :(得分:3)

  

我尝试过直接的Base64编码,但是对于一些较小的数字,编码的字符串比将数字存储为字符串更长

二进制字节数据的Base64编码将使其更长,大约三分之一。它不应该缩短,而是允许以非二进制安全的格式安全传输二进制数据。

然而,基数64比数字(或字节数据)的十进制表示更紧凑,即使它比基数256(原始字节数据)更紧凑。直接在base 64中编码你的数字将使它们比十进制更紧凑。这样就可以了:

private static final String base64Chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

static String encodeNumber(long x) {
    char[] buf = new char[11];
    int p = buf.length;
    do {
        buf[--p] = base64Chars.charAt((int)(x % 64));
        x /= 64;
    } while (x != 0);
    return new String(buf, p, buf.length - p);
}

static long decodeNumber(String s) {
    long x = 0;
    for (char c : s.toCharArray()) {
        int charValue = base64Chars.indexOf(c);
        if (charValue == -1) throw new NumberFormatException(s);
        x *= 64;
        x += charValue;
    }
    return x;
}

使用此编码方案,Long.MAX_VALUE将是字符串H__________,长度为11个字符,与其长度为19个字符的十进制表示9223372036854775807进行比较。最多约1600万的数字仅适合4个字符。那差不多就像你得到它一样短。 (从技术上讲,还有另外两个不需要在URL中编码的字符:. and ~。你可以将它们合并到基数66,对于某些数字来说这可能是一个较短的smidgin,尽管这看起来有点迂腐。)

答案 1 :(得分:1)

假设您没有进行任何压缩,并且您将自己限制为URL安全字符,那么以下过程将为您提供最紧凑的编码。

  1. 列出所有网址安全字符
  2. 算上他们。假设你有N。
  3. 用基数N表示你的数字,第一个字符代表0,第二个字符代表1,依此类推。

  4. 那么,压缩呢......

    如果您假设您所代表的数字在其范围内均匀分布,那么就没有真正的压缩机会。

    否则, potential 用于压缩。如果您可以减小公共数字的大小,那么通常可以通过压缩实现节省。这就是霍夫曼编码的工作原理。

    但缺点是在这个级别的压缩在数字范围内并不完美。它减少了一些数字的大小,但它不可避免地增加了其他数字的大小。


    那么这对您的用例意味着什么?

    我认为这意味着你正在以错误的方式看问题。您不应该针对每个数字的最小编码大小。您的目标应该是平均最小化...平均数量的实际分布。

答案 2 :(得分:1)

为了扩展Stephen C的答案,这里有一段代码转换为base 62(但你可以通过在digits字符串中添加更多字符来增加这一点(只需选择哪些字符有效对你而言):

public static String toString(long n) {
   String digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
   int base = digits.length();
   String s = "";
   while (n > 0) {
      long d = n % base;
      s = digits.charAt(d) + s;
      n = n / base;
   }
   return s;
}

这永远不会导致字符串表示长于数字。