了解散列算法的位和字节

Posted

技术标签:

【中文标题】了解散列算法的位和字节【英文标题】:Understanding bits and bytes of a hashing algorithm 【发布时间】:2021-08-04 10:09:33 【问题描述】:

在question 中关于一个名为 djb2 的非常简单的散列算法,作者想知道为什么在算法中选择了数字 33(参见下面的 C 代码)。

unsigned long;
hash(unsigned char *str)

    unsigned long hash = 5381;
    int c;

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

    return hash;

在最佳答案中,第 2 点谈到了散列累加器以及它如何制作自己的两个副本,然后它谈到了传播。

有人能解释一下“复制自己”和答案2的“传播”是什么意思吗?

【问题讨论】:

【参考方案1】:

第 2 步被引用是这样的:

    从移位和加法实现中可以看出,使用 33 会复制哈希累加器中的大部分输入位,然后将这些位分散到相对较远的位置。这有助于产生良好的雪崩。使用较大的移位将复制较少的位,使用较小的移位将使位交互更加局部,并使交互传播所需的时间更长。

33 是 32+1。这意味着,由于乘法是可分配的,hash * 33 = (hash * 32) + (hash * 1) - 或者换句话说,制作 hash 的两个副本,将其中一个向左移动 5 位,然后将它们相加,这就是 (hash &lt;&lt; 5) + hash 在更直接的方式。

【讨论】:

这是否假设我们正在处理 64 位机器?如果是这样,我们可以对每个字执行更多操作,从而减少对磁盘的 I/O?我的意思是,为什么答案 2 很重要? @GoldenRetriever 64 位并不是必需的,而且 djb2 的设计也没有考虑到这一点(不可能,它可以追溯到 1991 年)。我们当然可以使用更多的算术运算来计算出更好的散列。djb2 不是一个非常高质量的散列,尤其是与现代 64 位散列相比 1.难道我们不能使用除 33 之外的另一个乘法并仍然获得两个副本吗? 2. 为什么当使用更大的移位时,它会复制更少的位,反之亦然? 任何 2 的 2 次方之和都会产生两个副本(您可以使用更多副本进行更多混合)。较大的移位会从哈希顶部丢弃更多位,并且不要混合哈希的最低位。实际上可以包含大班次,但次大班班效果会很差。将0x80000001 视为乘数,会非常糟糕。 位移5是乘以32,这里乘以33是因为hash本身也加了

以上是关于了解散列算法的位和字节的主要内容,如果未能解决你的问题,请参考以下文章

了解位和偏移量的 C 要求 [关闭]

想懂区块链?哈希算法先了解一下!

我们通常说的中央处理器64位是啥意思

雪花算法(02)算法中的位运算

sh 有用的位和pices

常用的位操作