文字列を3つの短い文字列に分割します(3で割り切れない場合、最後の文字列は他の2つより長くなります)。それぞれに対して「短い」アルゴリズムを実行し、結果を連結します。
私はコードを書くことができましたが、質問の質に基づいて、ここからそれを取ることができると思います!
編集:そのアドバイスは十分ではないことが判明しました。元のCRC16コードに重大な欠陥があります。つまり、次のような行です。
j = Val("&H" + Mid(txt, nC, 2))
これは、16進値として解釈できるテキストのみを処理します。小文字と大文字は同じであり、アルファベットの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("A2")
などに配置できます。楽しみのために、「新しく改良された」hash4アルゴリズムを使用して、それらがどのように比較されるかを確認することもできます。衝突をカウントするためのピボットテーブルを作成しました。hash12
アルゴリズムには何もありませんでした。。には3つしかありませんでしたhash4
。これから、作成方法を理解できると確信していますhash8
。あなたの質問からの「ユニークである必要はない」は、おそらく「改善された」hash4
があなたが必要とするすべてであることを示唆しています。
原則として、4文字の16進数は64kの一意の値を持つ必要があります。したがって、同じハッシュを持つ2つのランダムな文字列の可能性は64kに1つです。400個の文字列がある場合、400 x 399/2の「衝突の可能性のあるペア」〜80kの機会があります(非常にランダムな文字列があると仮定)。したがって、サンプルデータセットで3つの衝突を観察することは、不合理なスコアではありません。文字列の数Nが増えると、衝突の確率はNの2乗になります。hash12に追加の32ビットの情報があると、N> 20 M程度のときに衝突が発生することが予想されます(手振り、in-my-頭の数学)。
明らかに、hash12コードをもう少しコンパクトにすることができます。そして、それを任意の長さに拡張する方法を簡単に理解できるはずです。
ああ-そして最後にもう1つ。RCアドレス指定を有効にしている場合=CRC16("string")
、スプレッドシートの数式として使用すると、追跡が難しい#REF
エラーが発生します...そのため、名前を変更しましたhash4