我定义了以下结构(名称是匿名的,但数据类型是正确的):
Public Type ExampleDataItem
Limit As Integer ' could be any value 0-999
Status As Integer ' could be any value 0-2
ValidUntil As Date ' always a valid date
End Type
Public Type ExampleData
Name As String ' could be 5-20 chars long
ValidOn As Date ' could be valid date or 1899-12-30 representing "null"
Salt As Integer ' random value 42-32767
Items(0 To 13) As ExampleDataItem
End Type
我想为ExampleData
实例生成32位哈希码。最小化哈希冲突非常重要,性能和数据顺序并不重要。
到目前为止,我已经(伪代码):
Long
值。Long
值放在一起。我无法发布我的代码,因为它严重依赖于实用程序类来进行序列化,但是如果有人想看到它,那么我会发布它。
这样可以,或者有人可以建议更好的方法吗?
修改
此代码用于实现软件许可系统的一部分。散列的目的是确认最终用户输入的数据是否等于技术支持人员输入的数据。因此哈希必须:
查找,唯一性测试或将ExampleData
实例存储在任何类型的集合中都不需要散列,但仅用于上述一个目的。
答案 0 :(得分:3)
你能使用CRC32吗? Steve McMahon有an implementation。将其与一些base32编码相结合,你就可以通过手机阅读短文。
答案 1 :(得分:0)
你可能会过度思考它,或者我不理解这个问题。你基本上可以哈希(CStr(Salt)+ Name + CStr(ValidOn)+ Anyotherstrings)。
没有特别需要经历序列化为字节数组和异或值的过程。事实上,以这种方式将值组合在一起更有可能在您不打算的情况下创建哈希冲突。
编辑:我想我现在明白了。您是通过将数据一起进行异或来创建自己的哈希值吗?不幸的是,很可能会发生碰撞。我知道VB6不包含任何散列算法,因此您最好导入并使用Phil Fresle's SHA256 implementation之类的东西。
答案 2 :(得分:0)
编辑:此问题现在已经过编辑,以澄清目标是检测输入错误,而不是最大限度地减少完全不同的值之间的冲突。在这种情况下,Dan F's answer是最好的恕我直言,而不是我在下面提供的(尽管很棒)。
您可以使用Microsoft CryptoAPI而不是滚动自己的哈希算法。
编辑:发表评论。如果您坚持使用32位值,则很难最小化哈希冲突。我的algorithm book建议使用Horner的方法作为一个不错的通用哈希算法。我现在没有时间在VB6中找到更多信息和实现。 CopyMemory可能会有用:)
答案 3 :(得分:0)
考虑到性能不是一个目标,如果文件大小不重要,并且您希望每个项目具有唯一值。只需添加ID字段即可。它的数据类型是一个字符串。然后使用此函数生成GUID。这将是一个唯一的ID。使用它作为dictonary或集合的关键。
Public Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Public Type GUID2 '15 BYTES TOTAL
Data1(14) As Byte
End Type
Public Declare Function CoCreateGuid Lib "OLE32.DLL" (pGuid As GUID) As Long
Public Function GetGUID() As String
Dim VBRIG_PROC_ID_STRING As String
VBRIG_PROC_ID_STRING = "GetGUID()"
Dim lResult As Long
Dim lguid As GUID
Dim MyguidString As String
Dim MyGuidString1 As String
Dim MyGuidString2 As String
Dim MyGuidString3 As String
Dim DataLen As Integer
Dim StringLen As Integer
Dim i As Integer
On Error GoTo error_olemsg
lResult = CoCreateGuid(lguid)
If lResult = 0 Then
MyGuidString1 = Hex$(lguid.Data1)
StringLen = Len(MyGuidString1)
DataLen = Len(lguid.Data1)
MyGuidString1 = LeadingZeros(2 * DataLen, StringLen) & MyGuidString1
'First 4 bytes (8 hex digits)
MyGuidString2 = Hex$(lguid.Data2)
StringLen = Len(MyGuidString2)
DataLen = Len(lguid.Data2)
MyGuidString2 = LeadingZeros(2 * DataLen, StringLen) & Trim$(MyGuidString2)
'Next 2 bytes (4 hex digits)
MyGuidString3 = Hex$(lguid.Data3)
StringLen = Len(MyGuidString3)
DataLen = Len(lguid.Data3)
MyGuidString3 = LeadingZeros(2 * DataLen, StringLen) & Trim$(MyGuidString3)
'Next 2 bytes (4 hex digits)
GetGUID = MyGuidString1 & MyGuidString2 & MyGuidString3
For i = 0 To 7
MyguidString = MyguidString & Format$(Hex$(lguid.Data4(i)), "00")
Next i
'MyGuidString contains last 8 bytes of Guid (16 hex digits)
GetGUID = GetGUID & MyguidString
Else
GetGUID = "00000000" ' return zeros if function unsuccessful
End If
Exit Function
error_olemsg:
GetGUID = "00000000"
Exit Function
End Function
Public Function LeadingZeros(ExpectedLen As Integer, ActualLen As Integer) As String
LeadingZeros = String$(ExpectedLen - ActualLen, "0")
End Function