web-dev-qa-db-fra.com

Pourquoi les 5381 et 33 sont-ils si importants dans l'algorithme djb2?

algorithme djb2 a une fonction de hachage pour les chaînes.

unsigned long hash = 5381;
int c;

while (c = *str++)
    hash = ((hash << 5) + hash) + c; /* hash * 33 + c */

Pourquoi les 5381 et 33 sont-ils si importants?

55
Vishnu Pedireddi

Cette fonction de hachage est similaire à un Linear Congruential Generator (LCG - une classe simple de fonctions qui génèrent une série de nombres pseudo-aléatoires), qui a généralement la forme:

X = (a * X) + c;  // "mod M", where M = 2^32 or 2^64 typically

Notez la similitude avec la fonction de hachage djb2 ... a = 33, M = 2 ^ 32. Pour qu'un LCG ait une "période complète" (c'est-à-dire aussi aléatoire que possible), a doit avoir certaines propriétés:

  • a-1 est divisible par tous les facteurs premiers de M (a-1 est 32, qui est divisible par 2, le seul facteur premier de 2 ^ 32)
  • a-1 est un multiple de 4 si M est un multiple de 4 (oui et oui)

De plus, c et [~ # ~] m [~ # ~] sont censés être relativement premiers (ce qui est vrai pour les valeurs impaires de c ).

Donc, comme vous pouvez le voir, cette fonction de hachage ressemble un peu à un bon LCG. Et en ce qui concerne les fonctions de hachage, vous en voulez une qui produit une distribution "aléatoire" des valeurs de hachage étant donné un ensemble réaliste de chaînes d'entrée.

Quant à savoir pourquoi cette fonction de hachage est bonne pour les chaînes, je pense qu'elle a un bon équilibre d'être extrêmement rapide, tout en fournissant une distribution raisonnable des valeurs de hachage. Mais j'ai vu de nombreuses autres fonctions de hachage qui prétendent avoir de bien meilleures caractéristiques de sortie, mais impliquaient beaucoup plus de lignes de code. Par exemple, voir cette page sur les fonctions de hachage

EDIT: Cette bonne réponse explique pourquoi 33 et 5381 ont été choisis pour des raisons pratiques.

37
Dustin Boswell

33 a été choisi parce que:

1) Comme indiqué précédemment, la multiplication est facile à calculer en utilisant shift et add.

2) Comme vous pouvez le voir sur le décalage et l'ajout d'implémentation, l'utilisation de 33 crée deux copies de la plupart des bits d'entrée dans l'accumulateur de hachage, puis répartit ces bits relativement loin. Cela aide à produire une bonne avalanche. L'utilisation d'un décalage plus grand dupliquerait moins de bits, l'utilisation d'un décalage plus petit garderait les interactions binaires plus locales et rendrait les interactions plus longues à se propager.

3) Le décalage de 5 est relativement premier à 32 (le nombre de bits dans le registre), ce qui aide à l'avalanche. Bien qu'il reste suffisamment de caractères dans la chaîne, chaque bit d'un octet d'entrée finira par interagir avec chaque bit d'entrée précédent.

4) Le décalage de 5 est une bonne quantité de décalage lorsque l'on considère les données de caractère ASCII. Un caractère ASCII peut être considéré comme un caractère 4 bits) sélecteur de type et un sélecteur de type de caractère à 4 bits. Par exemple, les chiffres ont tous 0x3 dans les 4 premiers bits. Ainsi, un décalage de 8 bits ferait interagir les bits avec une certaine signification avec d'autres bits qui ont la même signification. Un décalage de 4 ou 2 bits produirait de la même manière de fortes interactions entre des bits de même sensibilité. Le décalage de 5 bits fait que la plupart des quatre bits de poids faible d'un caractère interagissent fortement avec la plupart des 4 bits supérieurs de la même personnage.

Comme indiqué ailleurs, le choix du 5381 n'est pas trop important et de nombreux autres choix devraient également fonctionner ici.

Ce n'est pas une fonction de hachage rapide car elle traite l'entrée d'un caractère à la fois et n'essaie pas d'utiliser le parallélisme au niveau de l'instruction. Il est cependant facile à écrire. La qualité de la sortie divisée par la facilité d'écriture du code est susceptible de frapper un point idéal.

Sur les processeurs modernes, la multiplication est beaucoup plus rapide qu'elle ne l'était lorsque cet algorithme a été développé et d'autres facteurs de multiplication (par exemple 2 ^ 13 + 2 ^ 5 + 1) peuvent avoir des performances similaires, une sortie légèrement meilleure et être légèrement plus faciles à écrire.

Contrairement à une réponse ci-dessus, une bonne fonction de hachage non cryptographique ne veut pas produire une sortie aléatoire. Au lieu de cela, étant donné deux entrées presque identiques, il souhaite produire des sorties très différentes. Si vos valeurs d'entrée sont distribuées de manière aléatoire, vous n'avez pas besoin d'une bonne fonction de hachage, vous pouvez simplement utiliser un ensemble arbitraire de bits à partir de votre entrée. Certaines des fonctions de hachage modernes (Jenkins 3, Murmur, probablement CityHash) produisent une meilleure distribution des sorties que les entrées données aléatoires qui sont très similaires.

23
Chuck Simmons

Sur 5381, Dan Bernstein (djb2) dit dans cet article :

[...] pratiquement tout bon multiplicateur fonctionne. Je pense que vous vous inquiétez du fait que 31c + d ne couvre aucune plage raisonnable de valeurs de hachage si c et d sont compris entre 0 et 255. C'est pourquoi, quand j'ai découvert la fonction de hachage 33 et commencé à l'utiliser dans mes compresseurs , J'ai commencé avec une valeur de hachage de 5381. Je pense que vous constaterez que cela fait aussi bien qu'un multiplicateur 261.

Le fil entier est ici si vous êtes intéressé.

Ozan Yigit a ne page sur les fonctions de hachage qui dit:

[...] la magie du nombre 33 (pourquoi il fonctionne mieux que de nombreuses autres constantes, principales ou non) n'a jamais été suffisamment expliquée.
20
Matt Curtis

Peut-être parce que 33 == 2^5 + 1 Et de nombreux algorithmes de hachage utilisent 2^n + 1 Comme multiplicateur?

Crédit à Jerome Berger

Mise à jour:

Cela semble être confirmé par la version actuelle du progiciel djb2 originaire de: cdb

Les notes que j'ai liées pour décrire le cœur de l'algorithme de hachage comme utilisant h = ((h << 5) + h) ^ c pour faire le hachage ... x << 5 Est un moyen matériel rapide d'utiliser 2 ^ 5 comme multiplicateur.

9
John Weldon