将大数(或字符串)压缩成小值我的ASP.NET页面有如下查询字符串参数:...?IDs=1000000012,1000000021,1000000013,1000000022&...在这种情况下,IDs参数将始终包含由某些内容分隔的数字。目前有4个数字,但通常在3到7之间。现在,我正在寻找将每个大数字从上面转换为最小可能值的方法;具体压缩IDs查询字符串参数的值。欢迎压缩每个数值算法或压缩ID查询字符串参数的整个值。编解码都不是问题;只有值ID查询字符串参数被压缩。为ID创建一些唯一的小值,然后从一些超出范围的数据源中检索它们的值。有没有算法把这些大数压缩成小值或者把IDs查询字符串参数的值压缩到一起?您基本上需要这么多空间来存储您的数字,因为您使用基数10表示它们。改进是使用基数16(十六进制)。因此,例如,您可以将255(3位数字)表示为ff(2位数字)。您可以通过使用更大的数字基数来进一步理解这个概念……作为有效查询字符串参数的所有字符的集合:AZ、az、0-9、'。','-','~','_','+'这为您提供了67个字符的基数(请参阅Querypedia上的维基百科)。查看此SOpost,了解将基数10转换为任意数字基数的方法。编辑:在链接的SOpost中,请参阅此部分:stringxx=IntToString(42,newchar[]{'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=(字符在数组中的位置)示例:输入为BA1。TOTAL现在是1(因为“1”在数组中的位置1)现在查看第一个字符左侧的下一个字符以找到它在数组中的位置。TOTAL+=47*(字符在数组中的位置)示例:输入为BA1。TOTAL现在是(47*11)+1=518现在查看前一个字符左侧的下一个字符,以找到它在数组中的位置。TOTAL+=47*47*(字符在数组中的位置)例:输入为BA1。现在总计(47*47*10)+(47*11)+1=243508等等。我建议您编写一个单元测试,将一组以10为基数的数字转换为以47为基数,然后再转换回来,以确保转换代码正常工作。请注意如何用47进制中的3位数字表示10进制中的6位数字?你的号码范围是多少?假设它们可以放入16位整数中,我会:作为额外的好处,您不再需要逗号字符,因为您知道每个数字都是2个字节。或者,如果这还不够好,我会使用zlib压缩整数流,然后使用zlib压缩流作为base64。如果16位的范围不够大(例如,如果您确实需要1,000,000,000范围内的数字),您也可以切换到32位整数。编辑:也许为时已晚,但这里的现实可能会满足您的需求:usingSystem;使用System.Collections.Generic;使用System.Linq;使用系统文本;namespaceScratch{classProgram{staticvoidMain(string[]args){//varids=new[]{1000000012,1000000021,1000000013,1000000022};varrand=newRandom();varids=newint[rand.Next(20)];for(vari=0;iids){Console.Write("nIDs:");布尔逗号=假;foreach(ids中的id变量){if(comma){Console.Write(",");}else{逗号=true;}Console.Write(id);}控制台.WriteLine();}publicstaticstringIdsToString(ICollectionids){varallbytes=newList();foreach(ids中的id){varbytes=BitConverter.GetBytes(id);allbytes.AddRange(字节);}varstr=Convert.ToBase64String(allbytes.ToArray(),Base64FormattingOptions.None);返回str.Replace('+','-').Replace('/','_').Replace('=','.');}publicstaticICollectionStringToIds(stringidstring){varresult=newList();varstr=idstring.Replace('-','+').Replace('_','/').替换('.','=');varbytes=Convert.FromBase64String(str);for(vari=0;i这是另一个非常简单的解决方案,它应该为N+delta形式的一组数字提供良好的压缩,其中N是一个大常数publicint[]compress(int[]input){int[]res=input.clone();Arrays.sort(res);for(inti=1;i这应该将集合{1000000012,1000000021,1000000013,1000000022}减少到列表[1000000012,1,9,1]然后你可以通过像另一个一样用base47编码表示数字来进一步压缩如答案中所述。使用简单的十进制编码,从44个字符到16个字符;即63%。(使用base47将提供更多压缩)。如果排序id不可接受,那么压缩就不行了。对于这个例子,{1000000012,1000000021,1000000013,1000000022}压缩到列表[1000000012,9,-8,9]。对于这个例子,就是只有一个字符。无论哪种方式,这都比通用压缩算法或编码方案更好......对于这种输入。如果唯一的问题是URL长度,你可以将数字转换为base64字符,然后转换它们回到服务器端的数字。你得到的ID有多模糊?如果按数字顺序,ID是随机的,那么我将要提出的方法就不会很有效。但是,如果您作为示例提供的ID代表您将获得的类型,那么以下方法是否可行?我通过示例激发了这个想法...例如,您将1000000012作为要压缩的ID。为什么不将其存储为[{1},{0,7},{12}]?这意味着第一个数字是1,后面是7个零,然后是12。因此,如果我们使用符号{x}来表示x的一个实例,并且如果我们使用{x,y}来表示x的y次连续出现。您可以通过一些模式匹配和/或函数拟合来扩展它。例如,模式匹配:1000100032将是[{1000,2}{32}]。比如函数拟合:如果你的ID是10位,把ID拆分成两个5位的数字,存入经过这两个点的直线方程。如果ID=1000000012,则y1=10000,y2=12。因此,您的斜率为-9988,截距为10000(假设x1=0,x2=1)。在这种情况下,这不是一个改进,但如果数字更随机,它可能是。同样,您可以使用分段线性函数来存储ID序列。无论如何,这主要取决于您的ID的结构。我假设你这样做是为了解决请求URL长度限制......其他答案建议以十六进制、base47或base64编码十进制ID数字,但你可以(理论上)使用LZW(或类似的)压缩id列表)做得更好。根据ID列表中的冗余程度,即使将压缩字节重新编码为文本也可以显着减少40%以上。简而言之,我建议您找到一个用Javascript实现的现成文本压缩库,并使用它来压缩客户端的ID列表。然后使用base47/base64对压缩的字节串进行编码,并将编码后的字符串作为URL参数传递。在服务器端做相反的事情;即解码然后解压缩。编辑:作为一项实验,我创建了一个包含36个不同标识符的列表,例如您提供的标识符,并使用gzip对其进行了压缩。原始文件396字节,压缩文件101字节,压缩+base64文件138字节。整体减少了65%。对于较大的文件,压缩率实际上可以提高。但是,当我尝试使用较小的输入集(例如只有4个原始标识符)时,我没有得到压缩并且编码后的大小大于原始大小。谷歌“lzwlibraryjavascript”理论上,可能有更简单的解决方案。将参数作为“发布数据”而不是在请求URL中发送,并让浏览器使用它理解的编码之一应用压缩。这节省了更多的成本,因为不需要将压缩数据编码成合法的URL字符。问题是让浏览器压缩请求......并以独立于浏览器的方式进行。以上就是C#学习教程的全部内容:将大数(或字符串)压缩成小值。如果对你有用,需要了解更多C#学习教程,希望大家多多关注---本文来自网络收藏,不代表立场,如涉及侵权,请指教点击右侧联系管理员删除。如需转载请注明出处:
