【问题标题】:Is there a name for this hash function?这个哈希函数有名字吗?
【发布时间】:2019-08-15 07:07:50
【问题描述】:

我使用Elk Scheme interpreter 已经有一段时间了,有时也会浏览它的源代码。

我注意到它在 symbol.c 中包含以下哈希函数:

int Hash (char const *str, unsigned int len) {
    register int h;
    register char const *p, *ep;

    h = 5 * len;
    if (len > 5)
        len = 5;
    for (p = str, ep = p+len; p < ep; ++p)
        h = (h << 2) ^ *p;
    return h & 017777777777;
}

源代码中没有描述函数的内容。

这个哈希函数有名字吗?
散列方案是否记录在某处?

【问题讨论】:

  • 那东西很旧。我想知道在方案代码中是否可以看到方案中的哈希值,并且他们必须保留旧的哈希值。
  • @Joshua,它在代码库中仅使用一次:h = Hash (str, len) % OBARRAY_SIZE; 其中h 的类型为inth 用作数组的索引。
  • 看起来它基本上是一个具有不同常量的FNV 算法。奇怪的是它只看前 5 个字符...
  • 不幸的是,Subversion 提交日志也不包含有用的解释性消息。

标签: c hash


【解决方案1】:

因此,它与经典的 Fowler-Noll-Vo 哈希算法本质上是相同的,但它不是使用专门选择的素数作为哈希乘数,而是使用 4(将数字左移 2 与乘以4)。哈希的初始种子值也不一样; 5 * len 而不是一个常量值。

它只对字符串的前五个字符进行哈希处理,这是一个奇怪的选择,我相信作者有充分的理由。

最后一行return h &amp; 017777777777; 也很有趣。假设一个典型的 32 位 2 的补码 intINT_MAX,该八进制常数是。如果计算 64 位哈希但仅返回低 32 位,那么您会看到这种情况,但在 32 位类型上它是无操作的。也许作者对更大 int 类型的系统的可移植性感到偏执?但是,如果它只用于返回的哈希值取模数组长度的那个地方,那何必呢?或者,h 可能是一个 unsigned int,但他们不想使用该类型的全部范围(或者确保它在变成有符号值时永远不会是负数)?

【讨论】:

  • return h &amp; 017777777777; 是有意义的,因为解释器已被移植到许多硬件平台。其中一个或多个可能使用 64 位来表示 int。我当然很欣赏这种远见。
  • 没有素数的 FNV 不是 FNV,我并不希望人们知道这一点。如果调用者不做 mod prime,那么它的 rehash 特性很差。
猜你喜欢
  • 2016-12-10
  • 2010-10-12
  • 2023-03-21
  • 2011-06-04
  • 2016-02-09
  • 1970-01-01
  • 2017-11-29
  • 2017-04-25
  • 1970-01-01
相关资源
最近更新 更多