将非常大的整数压缩成尽可能小的字符串

Compress very large Integers into smallest possible string

我想将整数(~20 位数字)压缩为带有符号的较小字符串。 我成功了,但它只适用于大约 16 位以下的整数。

我猜这是某种舍入错误。有谁知道如何修复它,或者使用其他方法将整数压缩为带有自定义字符的字符串?
提前致谢!


示例:

两种方式都有效:
822152842686533 => 6OKYXLtml
6OKYXLtml => 822152842686533

两种方式都不起作用:
25478562549632547 => 3OxGclFmZ9
3OxGclFmZ9 => 25478562549632553

private List<char> symbollist = new List<char> { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'x', 'y', 'z'};

private string Compress(decimal code)
    {
        if (code < 1)
            return "0";

        string codestring = "";

        List<char> charlist = new List<char>();
        while (code > 1)
        {
            charlist.Add(symbollist[(int)(code % symbollist.Count)]);
            code /= symbollist.Count;
        }
        for (int i = charlist.Count-1; i >=0; i--)
        {
            codestring += charlist[i];
        }
        return codestring;
    }
private decimal DeCompress(string code)
    {
        decimal codedec = 0;
        for (int i = 0; i < code.Length; i++)
        {
            codedec += symbollist.IndexOf(code[i]) * (decimal)System.Math.Pow(symbollist.Count, code.Length - 1 - i);
        }
        return codedec;
    }

因为您的 System.Math.Pow 使用的是 double,而不是 decimal,并且对于您较大的数字而言精度不够。 double 只有 52 位的尾数,而你的第二个例子是一个 55 位的整数。

反正你不需要幂函数,编码的时候也不需要反转数字。按照您生成它们的顺序,首先用最低有效数字编码。然后解码的时候,每次乘以基数,维护一个基数的n次方。添加时使用它来乘以每个数字。使用 decimal 算术进行所有乘法和加法,以保持所需的精度。

类似于:

private List<char> symbollist = new List<char> { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'x', 'y', 'z'};

private string Compress(decimal code)
    {
        string codestring = "";
        do
        {
            codestring += symbollist[(int)(code % symbollist.Count)];
            code = Decimal.Floor(code / symbollist.Count);
        } while (code >= 1);
        return codestring;
    }
private decimal DeCompress(string code)
    {
        if (code.Length == 0)
            return 0;
        decimal codedec = symbollist.IndexOf(code[0]);
        decimal pos = 1;
        for (int i = 1; i < code.Length; i++)
        {
            pos *= symbollist.Count;
            codedec += symbollist.IndexOf(code[i]) * pos;
        }
        return codedec;
    }

示例输入、编码、解码(使用 decimal 类型的所有尾数位):

79228162514264337593543950335
b8NYXtnuNafbQGBo4
79228162514264337593543950335

(注意:您的代码应该对分数的存在做一些处理。要么在编码之前删除分数,要么 return 出错。还要处理无效数字。)