Chaîne de hachage VBA
Comment puis-je obtenir un court de hachage d'une longue chaîne à l'aide de VBA Excel
Ce qui est donné
- Chaîne d'entrée n'est pas plus de 80 caractères
- D'entrée valide caractères sont les suivants: [0..9] [A_Z] . _ /
- Valide sortie caractères [0..9] [A_Z] [a_z] (en minuscules et en majuscules peuvent être utilisés)
- La sortie de hachage ne devrait pas être de plus de ~12 caractères (plus court, c'est encore mieux)
- Pas besoin d'être unique à tous car cela entraîne un trop long de hachage
Ce que j'ai fait jusqu'à présent
J'ai pensé cette SORTE de réponse est un bon début, car il génère un code de 4 chiffres Code Hexadécimal (CRC16).
Mais 4 chiffres étaient à peu. Dans mon test, avec plus de 400 chaînes de 20% ont obtenu un double quelque part d'autre.
La chance de générer une collision est trop élevé.
Sub tester()
For i = 2 To 433
Cells(i, 2) = CRC16(Cells(i, 1))
Next i
End Sub
Function CRC16(txt As String)
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 = 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
CRC16 = Hex$(Crc)
End Function
Comment reproduire
Vous pouvez copier ces 400 test de chaînes à partir de pastebin.
Coller Une colonne dans un nouveau classeur Excel et d'exécuter le code ci-dessus.
Q: Comment puis-je obtenir une chaîne de hachage qui est assez courte (12 caractères) et assez long pour obtenir un petit pourcentage de doublons.
source d'informationauteur nixda
Vous devez vous connecter pour publier un commentaire.
Diviser votre chaîne en trois courtes chaînes (si pas divisible par trois, le dernier sera plus long que les deux autres). Exécuter votre "court" de l'algorithme sur chaque, et concaténer les résultats.
Je pourrais écrire du code, mais en fonction de la qualité de la question, je pense que vous pouvez le prendre à partir d'ici!
EDIT: Il s'avère que ce conseil n'est pas assez. Il y a un grave défaut dans votre original CRC16 code - à savoir la ligne qui dit:
Ce ne gère qu'un texte qui peut être interprété en tant que valeurs hexadécimales: les minuscules et les majuscules sont les mêmes, et rien après F de l'alphabet est ignoré (autant que je puisse en dire). Que rien de bon sort à tous est un miracle. Si vous remplacez la ligne par
Les choses fonctionnent mieux chaque code ASCII au moins commence la vie de sa propre valeur.
Combinant cette modification à la proposition que j'ai fait, vous obtenez le code suivant:
Vous pouvez placer ce code dans votre feuille de calcul en tant que
=hash12("A2")
etc. Pour le fun, vous pouvez également utiliser la fonction "nouveau et amélioré" hash4 algorithme, et de voir comment ils se comparent. J'ai créé un tableau croisé dynamique à compter de collisions - il n'y avait personne pour l'hash12
algorithme, et seulement 3 pour lehash4
. Je suis sûr que vous pouvez comprendre comment créerhash8
... à partir de cela. La "pas besoin d'être unique" à partir de votre question suggère que peut-être le "meilleur"hash4
est tout ce dont vous avez besoin.En principe, un caractère de quatre hex doit avoir de 64 ko de valeurs uniques: si la chance des deux chaînes aléatoires ayant le même hash serait de 1 à 64 ko. Lorsque vous avez de 400 chaînes, il y a 400 x 399 /2 "collision possible paires" ~ 80k possibilités (en supposant que vous avez eu très aléatoire de chaînes de caractères). L'observation de trois collisions dans l'échantillon de données est donc pas déraisonnable de score. Comme votre nombre de cordes N augmente, la probabilité de collisions se passe comme le carré de N., Avec le supplément de 32 bits d'information dans le hash12, vous vous attendez à voir les collisions lorsque N > 20 M (handwaving, dans-ma-tête-math).
Vous pouvez faire la hash12 code un peu plus compact, bien sûr - et il devrait être facile de voir comment l'étendre à toute la longueur.
Oh et une dernière chose. Si vous avez des RC aborder activé à l'aide de
=CRC16("string")
comme une feuille de calcul formule donne un dur-à-piste#REF
erreur... c'est pourquoi je l'ai renomméhash4
Peut-être que d'autres vont trouver cela utile.
J'ai recueilli des fonctions différentes pour générer un court hash d'une chaîne en VBA.
Je ne prends pas de crédit pour le code et toutes les sources sont citées.
=CRC16HASH(A1)
avec cette Code=CRC16NUMERIC(A1)
avec cette Code=CRC16TWICE(A1)
avec cette Code=SHA1TRUNC(A1)
avec cette Code=BASE64SHA1(A1)
avec cette CodeIci est mon test classeur avec tous les exemples de fonctions et un grand nombre de chaînes de test.
N'hésitez pas à ajouter vos propres fonctions.
Pour l'enregistrement, celui-ci génère rapidement un 32 bits de hachage avec un faible niveau de collision:
Alors que le ci-dessous n'est pas une fonction de hachage, je l'ai utilisé comme un moyen rapide de générer des id numérique qui ont un faible taux de collision sur une petite liste (assez petit pour vérifier par l'inspection).
Comment il Fonctionne: Colonne A contient les chaînes de caractères à partir de la ligne 2 à partir. Dans la ligne 1, A1 et B1 tenir un arbitraire de début et de fin de position à mi-chemin dans la chaîne. La formule utilise la première lettre de la chaîne et fixe lettre prises à partir de la mi-chaîne et utilise LEN() comme un "attiser la fonction" afin de réduire le risque de collisions.
Si les chaînes sont extraites d'une table de base de données avec des champs de largeur fixe, vous pouvez avoir besoin de couper les longueurs: