C# 将大数字(或字符串)压缩为小值

C# 将大数字(或字符串)压缩为小值,c#,algorithm,math,compression,logic,C#,Algorithm,Math,Compression,Logic,“我的ASP.NET页”具有以下查询字符串参数: …?IDs=1000000012,1000000021,1000000013,1000000022&... 在这里,IDs参数总是用数字分隔,在本例中,,。目前有4个数字,但通常介于3和7之间 现在,我正在寻找将上面的每个大数字转换为最小可能值的方法;具体压缩IDs查询字符串参数的值。无论是压缩每个数字算法还是压缩IDsquerystring参数的整数值都是受欢迎的 编码或解码不是问题;只需压缩值IDsquerystring参数 为ID

“我的ASP.NET页”具有以下查询字符串参数:

…?IDs=1000000012,1000000021,1000000013,1000000022&...
在这里,
IDs
参数总是用数字分隔,在本例中,
。目前有4个数字,但通常介于
3
7
之间

现在,我正在寻找将上面的每个大数字转换为最小可能值的方法;具体压缩
IDs
查询字符串参数的值。无论是压缩每个数字算法还是压缩
IDs
querystring参数的整数值都是受欢迎的

  • 编码或解码不是问题;只需压缩值
    IDs
    querystring参数
  • IDs
    创建一些唯一的小值,然后从某些数据源检索其值,这超出了范围

  • 是否有一种算法可以将如此大的数字压缩为较小的值,或者将
    IDs
    查询字符串参数的值一起压缩?

    基本上,您需要为数字留出很大的空间,因为您使用的是以10为基数来表示它们。一个改进是使用基数16(十六进制)。例如,您可以将255(3位)表示为ff(2位)

    你可以通过使用更大的基数来进一步理解这个概念。。。有效查询字符串参数的所有字符集:

    A-Z,A-Z,0-9,“,”-“,“~”,“',“+”

    这为您提供了67个字符的基数(请参阅)

    请看一看将基数10转换为任意数字基数的方法

    编辑:

    在链接的SO帖子中,查看以下部分:

    string xx = IntToString(42, 
                new 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','V','W','X','Y','Z',
                'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x'});
    
    这几乎就是你需要的。只需通过添加缺少的几个字符将其展开:

    yz-~_+

    那篇文章缺少一个返回10进制的方法。我不打算写它:-)但过程是这样的:

    定义一个我称之为TOTAL的计数器

    查看右侧的most字符,找到它在数组中的位置。
    TOTAL=(字符在数组中的位置) 示例:输入为BA1。总数现在是1(因为“1”在数组中的位置1)

    现在看第一个字符左边的下一个字符,找到它在数组中的位置。 总计+=47*(字符在数组中的位置) 示例:输入为BA1。总数现在是(47*11)+1=518

    现在查看前一个字符左侧的下一个字符,并找到它在数组中的位置。 总计+=47*47*(字符在数组中的位置) 示例:输入为BA1。总数现在是(47*47*10)+(47*11)+1=243508

    等等

    我建议您编写一个单元测试,将一组以10为基数的数字转换成以47为基数的数字,然后再转换回来,以确保转换代码正常工作


    请注意,您是如何用以47:-)为基数的3位数字表示以10为基数的6位数字的。

    如果唯一的问题是URL长度,您可以将数字转换为,然后在服务器端将其转换回数字。

    您的数字范围是多少?假设它们可以放入16位整数中,我会:

    • 将所有数字存储为(每个数字2个字节,范围为-32768到32767)
    • 构建一个16位整数的ByTestStream(在这里可能是一个不错的选择;至少,确保正确处理)
    • 对ByTestStream进行编码,对URL使用修改后的base64编码(网络约为每个数字3个字符)
    作为额外的奖励,您不再需要逗号字符,因为您知道每个数字是2个字节

    或者,如果这还不够好,我将使用压缩整数流,然后使用base64压缩zlib流。如果16位的范围不够大(即,如果您确实需要100000000范围内的数字),也可以切换到32位整数

    编辑:

    也许太晚了,但这里有一个实现,可以满足您的需要:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Scratch {
        class Program {
            static void Main(string[] args) {
                //var ids = new[] { 1000000012, 1000000021, 1000000013, 1000000022 };
                var rand = new Random();
                var ids = new int[rand.Next(20)];
                for(var i = 0; i < ids.Length; i++) {
                    ids[i] = rand.Next();
                }
    
                WriteIds(ids);
                var s = IdsToString(ids);
                Console.WriteLine("\nResult string is: {0}", s);
                var newIds = StringToIds(s);
                WriteIds(newIds);
                Console.ReadLine();
            }
    
            public static void WriteIds(ICollection<Int32> ids) {
                Console.Write("\nIDs: ");
                bool comma = false;
                foreach(var id in ids) {
                    if(comma) {
                        Console.Write(",");
                    } else {
                        comma = true;
                    }
                    Console.Write(id);
                }
                Console.WriteLine();
            }
    
            public static string IdsToString(ICollection<Int32> ids) {
                var allbytes = new List<byte>();
                foreach(var id in ids) {
                    var bytes = BitConverter.GetBytes(id);
                    allbytes.AddRange(bytes);                
                }
                var str = Convert.ToBase64String(allbytes.ToArray(), Base64FormattingOptions.None);
                return str.Replace('+', '-').Replace('/', '_').Replace('=', '.');
            }
    
            public static ICollection<Int32> StringToIds(string idstring) {
                var result = new List<Int32>();
                var str = idstring.Replace('-', '+').Replace('_', '/').Replace('.', '=');
                var bytes = Convert.FromBase64String(str);
                for(var i = 0; i < bytes.Length; i += 4) {
                    var id = BitConverter.ToInt32(bytes, i);
                    result.Add(id);
                }
                return result;
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用系统文本;
    名称空间划痕{
    班级计划{
    静态void Main(字符串[]参数){
    //var id=new[]{100000011000000210000001100000022};
    var rand=new Random();
    变量ID=新整数[rand.Next(20)];
    对于(变量i=0;i
    您获得的ID的模式如何?如果一位接一位,则ID为rando
    public int[] compress(int[] input) {
        int[] res = input.clone();
        Arrays.sort(res);
        for (int i = 1; i < res.length; i++) {
            res[i] = res[i] - res[i - 1];
        }
        return res;
    }