我有一个任意长度的字符串(比如5到2000个字符),我想计算一个校验和。
要求
我应该使用哪种算法?
更新:
UPDATE2
假设我得到以下字符串"Welcome to this website. Navigate using the flashy but useless menu above"
。
该视图中的字符串与linux中的gettext
类似。即用户只是写(在剃刀视图中)
@T("Welcome to this website. Navigate using the flashy but useless menu above")
现在我需要一种方法来识别该字符串,以便我可以从数据源中获取它(有几种数据源实现)。必须使用整个字符串作为键似乎有点低效,因此我正在寻找一种方法来生成一个密钥。
答案 0 :(得分:31)
那是不可能的。
如果无法存储以前的值,则无法创建小于字符串中信息的唯一校验和。
“合理独特”一词没有意义,要么是独特的,要么不是。
为了获得相当低的哈希冲突风险,您可以使用合理的大型哈希码。
例如,MD5算法产生一个16字节的哈希码。使用保留所有字符的某些编码(例如UTF-8)将字符串转换为字节数组,使用MD5
类计算哈希码,然后使用{{1}将哈希码字节数组转换为字符串} class:
BitConverter
输出:
string theString = "asdf";
string hash;
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create()) {
hash = BitConverter.ToString(
md5.ComputeHash(Encoding.UTF8.GetBytes(theString))
).Replace("-", String.Empty);
}
Console.WriteLine(hash);
答案 1 :(得分:8)
您可以使用加密Hash functions。其中大多数都可以在.Net
中找到例如:
var sha1 = System.Security.Cryptography.SHA1.Create();
byte[] buf = System.Text.Encoding.UTF8.GetBytes("test");
byte[] hash= sha1.ComputeHash(buf, 0, buf.Length);
//var hashstr = Convert.ToBase64String(hash);
var hashstr = System.BitConverter.ToString(hash).Replace("-", "");
答案 2 :(得分:3)
注意:这是对原始问题的回答。
假设您希望校验和存储在固定大小的变量(即整数)中,则无法满足第二个约束条件。
校验和必须是唯一的(无碰撞)
您无法避免冲突,因为会有比可能的校验和值更多的不同字符串。
答案 3 :(得分:2)
我意识到这篇文章几乎是古老的,但我偶然发现它并且在过去遇到了几乎相同的问题。我们需要查找nvarchar(8000)字段。
我们的解决方案是使用讨厌的查找字段的CHECKSUM创建一个持久的计算列。我们有一个自动递增的ID字段并且键入(校验和,id)
从表中读取时,我们编写了一个proc,它接受了查找文本,计算了校验和,然后在校验和相等且文本相同的地方进行了。
您可以根据上面的答案轻松地在应用程序级别执行校验和部分,并手动存储它们,而不是使用我们以DB为中心的解决方案。但重点是获得一个合理大小的索引键,以便您的文本比较针对一堆冲突而不是整个数据集运行。
祝你好运!答案 4 :(得分:1)
为保证唯一性,对于几乎无限大小的字符串,请将可变长度字符串视为一组串联的子字符串,每个子字符串均具有“ x个字符的长度”。您的哈希函数只需要确定最大子串长度的唯一性,然后生成一系列校验和编号即可生成值。将其视为具有一组校验和编号的等效网络IP地址。
您的碰撞问题是假设碰撞会强制采用较慢的搜索方法来解决每个碰撞。如果与散列对象的数量相比,它们的潜在冲突数量微不足道,那么总体而言,额外的开销将变为NIL。发生冲突的原因是表的大小小于对象的最大数量。并非必须如此,因为表格可能有“孔”,并且表格中的每个对象在该碰撞时可能都有对象的引用计数。仅当此计数大于1时,才会发生冲突或同一子字符串的多个实例。