C# 将大数字(或字符串)压缩为小值
“我的ASP.NET页”具有以下查询字符串参数: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
…?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个字符)
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;
}