VBA哈希字符串
如何使用Excel VBA获取长字符串的短哈希 给出了什么VBA哈希字符串,vba,hash,excel-2003,Vba,Hash,Excel 2003,如何使用Excel VBA获取长字符串的短哈希 给出了什么 输入字符串长度不超过80个字符 有效输入字符为:[0..9][A_Z]。\uz/ 有效的输出字符为[0..9][A_Z][A_Z](可以使用小写和大写) 输出哈希不应超过12个字符(越短越好) 根本不需要是唯一的,因为这将导致太长的散列 我到目前为止所做的事情 我认为这是一个好的开始,因为它生成了一个4位十六进制代码(CRC16) 但4位数字太小了。在我对400个字符串的测试中,20%在其他地方得到了一个副本。 产生碰撞的几率太高
- 输入字符串长度不超过80个字符
- 有效输入字符为:[0..9][A_Z]。\uz/李>
- 有效的输出字符为[0..9][A_Z][A_Z](可以使用小写和大写)
- 输出哈希不应超过12个字符(越短越好)
- 根本不需要是唯一的,因为这将导致太长的散列
产生碰撞的几率太高
子测试仪()
对于i=2到433
单元(i,2)=CRC16(单元(i,1))
接下来我
端接头
函数CRC16(txt作为字符串)
暗x等长
Dim mask、i、j、nC、Crc作为整数
作为字符串的Dim c
Crc=&HFFFF
对于nC=1到Len(txt)
j=Val(“&H”+Mid(txt,nC,2))
Crc=Crc异或j
对于j=1到8
掩码=0
如果Crc/2 Int(Crc/2),则掩码=&HA001
Crc=Int(Crc/2)和&H7FFF:Crc=Crc异或掩码
下一个j
下一个nC
CRC16=十六进制$(Crc)
端函数
如何复制
您可以复制这些400。将它们粘贴到新Excel工作簿中的A列,并执行上面的代码
Q:如何获取足够短(12个字符)且足够长的字符串哈希,以获得少量重复。将字符串拆分为三个较短的字符串(如果不能被三整除,则最后一个字符串将比其他两个长)。对每个对象运行“short”算法,并连接结果 我可以写代码,但基于问题的质量,我认为你可以从这里开始 编辑:事实证明,这些建议是不够的。您的原始CRC16代码中有一个严重缺陷,即以下代码行:
j = Val("&H" + Mid(txt, nC, 2))
这只处理可以解释为十六进制值的文本:小写和大写字母是相同的,字母表中F之后的任何内容都被忽略(据我所知)。任何好的东西都会出现,这是一个奇迹。如果您将线路替换为
j = asc(mid(txt, nC, 1))
事情进展得更好——每一个ASCII码至少都是以其自身的价值开始生命的
将此更改与我之前提出的建议相结合,您将获得以下代码:
Function hash12(s As String)
' create a 12 character hash from string s
Dim l As Integer, l3 As Integer
Dim s1 As String, s2 As String, s3 As String
l = Len(s)
l3 = Int(l / 3)
s1 = Mid(s, 1, l3) ' first part
s2 = Mid(s, l3 + 1, l3) ' middle part
s3 = Mid(s, 2 * l3 + 1) ' the rest of the string...
hash12 = hash4(s1) + hash4(s2) + hash4(s3)
End Function
Function hash4(txt)
' copied from the example
Dim x As Long
Dim mask, i, j, nC, crc As Integer
Dim c As String
crc = &HFFFF
For nC = 1 To Len(txt)
j = Asc(Mid(txt, nC)) ' <<<<<<< new line of code - makes all the difference
' instead of j = Val("&H" + Mid(txt, nC, 2))
crc = crc Xor j
For j = 1 To 8
mask = 0
If crc / 2 <> Int(crc / 2) Then mask = &HA001
crc = Int(crc / 2) And &H7FFF: crc = crc Xor mask
Next j
Next nC
c = Hex$(crc)
' <<<<< new section: make sure returned string is always 4 characters long >>>>>
' pad to always have length 4:
While Len(c) < 4
c = "0" & c
Wend
hash4 = c
End Function
函数hash12(作为字符串)
'从字符串s创建一个12个字符的哈希
Dim l为整数,l3为整数
尺寸s1为字符串,s2为字符串,s3为字符串
l=Len(s)
l3=整数(l/3)
s1=中部(s、1、l3)第一部分
s2=中部(s,l3+1,l3)'中部
s3=中间(s,2*l3+1)'字符串的其余部分。。。
hash12=hash4(s1)+hash4(s2)+hash4(s3)
端函数
函数hash4(txt)
"照搬例子,
暗x等长
Dim mask、i、j、nC、crc作为整数
作为字符串的Dim c
crc=&HFFFF
对于nC=1到Len(txt)
j=Asc(Mid(txt,nC))'20米左右(手工操作,在我的头脑中)
显然,您可以使hash12代码更紧凑一点,而且应该很容易看到如何将其扩展到任意长度
哦,还有最后一件事。如果启用了RC寻址,则使用=CRC16(“字符串”)
作为电子表格公式会出现难以跟踪的#REF
错误。。。这就是为什么我将其重命名为hash4
也许其他人会发现这很有用
我收集了一些不同的函数来在VBA中生成字符串的短哈希。我不相信这些代码,所有的资料都被引用了
- 函数:
与此=CRC16HASH(A1)
- 哈希是一个4个字符长的十六进制字符串
- 19行代码
- 4位长哈希=6895行中的624个冲突=9%冲突率
- 函数:
与此=CRC16NUMERIC(A1)
- 哈希是一个5位数的数字
- 92代码行
- 5位长哈希=6895行中的616次冲突=8.9%冲突率
- 功能:
与此=CRC16TWICE(A1)
- 哈希是一个8个字符长的十六进制字符串
- 哈希可以扩展到12/16/20等字符,以进一步降低冲突率
- 39行代码
- 8位长散列=6895行中的18次冲突=0.23%冲突率
- 函数:
与此=SHA1TRUNC(A1)
- 哈希是一个40个字符长的十六进制字符串
- 142行代码
- 可以被截断
- 4位哈希=6895行中的726次冲突=10.5%冲突率
- 5位哈希=6895行中的51次冲突=0.73%冲突率
- 6位哈希=6895行中的0冲突=0%冲突率
- 函数:
与此=BASE64SHA1(A1)
- 哈希是一个28个字符长的unicode字符串(区分大小写+特殊字符)
- 41代码行
- 需要.NET,因为它使用库“Microsoft MSXML”
- 可以被截断
- 4位哈希=6895行中的36次冲突=0.5%冲突率
- 5位哈希=6895行中的0个冲突=0%冲突率
您可以随意添加自己的函数。虽然下面的函数不是散列函数,但我已将其用作快速生成数字id的方法,该id在一个小列表上具有较低的冲突率(小到足以通过检查进行验证) 它的工作原理:A列保存从第2行开始的字符串。在第1行中,A1和B1在字符串的中间位置保持任意的开始和结束位置。该公式使用字符串的第一个字母和从字符串中间提取的固定字母,并使用LEN()作为“扇形函数”,以减少碰撞的机会
=CODE(A2)*LEN(A2) + CODE(MID(A2,$A$1,$B$1))*LEN(MID(A2,$A$1,$B$1))
如果从具有固定宽度字段的数据库表中提取字符串,则可能需要修剪长度:
=CODE(TRIM(C8))*LEN(TRIM(C8))
+CODE(MID(TRIM(C8),$A$1,1))*LEN(MID(TRIM(C8),$A$1,$B$1))
Public Function StrHash(text As String) As Long
Dim i As Long
StrHash = &H65D5BAAA
For i = 1 To Len(text)
StrHash = ((StrHash + AscW(Mid$(text, i, 1))) Mod 69208103) * 31&
Next
End Function
Public Function StrHash64(text As String) As String
Dim i&, h1&, h2&, c&
h1 = &H65D5BAAA
h2 = &H2454A5ED
For i = 1 To Len(text)
c = AscW(Mid$(text, i, 1))
h1 = ((h1 + c) Mod 69208103) * 31&
h2 = ((h2 + c) Mod 65009701) * 33&
Next
StrHash64 = Right("00000000" & Hex(h1), 8) & Right("00000000" & Hex(h2), 8)
End Function