1. 程式人生 > >djb2:一個產生簡單的隨機分布的哈希函數

djb2:一個產生簡單的隨機分布的哈希函數

相關 加法 lin generator func tin near img 累加

目錄

  • LCG算法
    • 示例代碼
  • djb2
    • 示例代碼
    • 為什麽選擇參數33和
      • 33 was chosen because:
      • 5381 was chosen because
  • 哈希選擇參考

LCG算法

djb2與LCG很類似,故先介紹 LCG。

LCG(linear congruential generator)算法是一個古老的產生隨機數的算法。由以下參數產生

參數 m a c X
性質 模數 乘數 加數 隨機數
作用 取模 移位 偏移 作為結果

LCG算法是如下的一個遞推公式,每下一個隨機數是當前隨機數向左移動 log2 a 位,加上一個 c,最後對 m 取余,使隨機數限制在 0 ~ m-1 內
技術分享圖片

從該式可以看出,該算法由於構成簡單,具有以下優點:

  • 計算速度快
  • 易於實現
  • 易於寫入硬件

以下是針對不同參數 lcg 產生隨機數的效果圖

技術分享圖片

可以看出,針對不同的參數,lcg產生的效果差別很大

以下是針對不同環境下的參數選擇

技術分享圖片

詳見wiki

示例代碼

def lcg(modulus, a, c, seed):
    while True:
        seed = (a * seed + c) % modulus
        yield seed

djb2

djb2是一個產生隨機分布的的哈希函數,與LCG的算法相似。

以下是 djb2 的哈希函數:

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

示例代碼


// generates a hash value for a sting
// same as djb2 hash function
//構造哈希函數 f(hash)= hash * 33 + c
unsigned int CountMinSketch::hashstr(const char *str) {
  unsigned long hash = 5381;
  int c;
  while (c = *str++) {
    hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
  }
  return hash;
}

本部分利用djb2處理字符串。
其中參數常有以下取值:
M=2^32

M常取一個較大的質數,以減少沖突。

由於哈希函數構造簡單,使用移位和相加的操作,所以計算速度快。

要註意hash值的計算,在不同機器上,可能會造成溢出的問題,可以及時對hash值取余。但是會增加計算開銷,造成hash範圍減小的問題。

為什麽選擇參數33和

33 was chosen because:

1) 乘法易於移位或相加

2) 從移位和加法實現中可以看到,使用33可以復制散列累加器中的大多數輸入位,然後將這些位相對地分散開來。這有助於形成好的雪崩現象。使用較大的移位將復制更少的位,使用較小的移位將使位交互更局部,並使交互擴展所需的時間更長。

3) 32 = 2^5,32 與移 5 位相關,有助於將每一個字符串的每一位比特都作用到最終的哈希值當中

4) 在考慮ASCII字符數據時,5的移位是一個很好的移位量。ASCII字符可以看作是4位字符類型選擇器和4位字符類型選擇器。前4位的數字都是0x3。因此,8位移位將導致具有特定含義的位與具有相同含義的其他位相互作用。4位或2位的移位同樣會在相似的位之間產生強烈的交互作用。5位的移位使得一個字符的4個低階位中的許多位與同一字符的4個上位中的許多強相互作用。

5381 was chosen because

1) 選擇5381並不太重要,很多其他的大的質數數也可以運行地很好。

哈希選擇參考

源自 https://stackoverflow.com/questions/1579721/why-are-5381-and-33-so-important-in-the-djb2-algorithm

djb2不是一個快速哈希函數,因為它每次處理輸入一個字符,並且不嘗試使用指令級並行。

在現代處理器,乘法時該算法要快得多了乘法和其他因素(如2 ^ 13 + 2 ^ 5 + 1)可能也有類似的表現,有更好的輸出,更容易寫。

一個好的非加密哈希函數不希望產生隨機輸出。相反,給定兩個幾乎完全相同的輸入,它希望產生完全不同的輸出。

如果你的輸入值是隨機分布的,你不需要一個好的哈希函數,你可以使用你輸入的任意一組比特。一些現代哈希函數(Jenkins 3, Murmur, probably CityHash)產生的輸出分布比高度相似的隨機輸入更好。

選擇哈希函數的詳細博客 https://blog.csdn.net/xu20082100226/article/details/52651212

djb2:一個產生簡單的隨機分布的哈希函數