• djb2:一个产生简单的随机分布的哈希函数


    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

  • 相关阅读:
    Java实现生产者消费者模式
    LRU结构(采用hashmap + 双向链表实现)
    自定义优先级队列PriorityQueue
    KdApiSearchDemo
    MongoDBHelper
    WebApiInvoker
    轨迹
    SignAttribute
    web api 压缩
    web api 缓存类
  • 原文地址:https://www.cnblogs.com/vancasola/p/9951686.html
Copyright © 2020-2023  润新知