【问题标题】:Djb2 hash function by Dan Bernstein : Why use bitwise operator when we can just multiply by 33?Dan Bernstein 的 Djb2 哈希函数:当我们只能乘以 33 时,为什么还要使用按位运算符?
【发布时间】:2021-10-18 22:37:53
【问题描述】:

在 Dan Bernstein 著名的 Djb2 哈希函数中,我看到使用按位运算符是首选,但为什么要使用它而不是简单的乘法呢?是不是更快?

(散列

// Hashes word to a number
unsigned int hash(const char *word)
{
    // Djb2 hash function by Dan Bernstein
    unsigned long hash = 5381;
    int c;
    while ((c = *word++))
    {
        hash = ((hash << 5) + hash) + tolower(c); /* hash * 33 + c */
    }

    return hash % N;
}

【问题讨论】:

  • 欢迎来到 Stack Overflow。 softwareengineering.stackexchange.com/questions/234967/… 会回答你的问题吗?
  • 您可能想检查您的 优化 asm 输出,因为如果在这种情况下该计算的 both 版本我不会感到惊讶最终生成相同的功能代码。 clang 12.01 和 gcc 11.2 都将生成 shift-arithmetic-left 5 和后续添加,无论您是否明确按照所示代码指定 仅使用 (hash * 33)。
  • 任何现代编译器都会为两者生成相同的代码(godbolt 确认),但在 1991 年设计此算法时可能并非如此。

标签: c hash bit-manipulation


【解决方案1】:

既然我们只能乘以 33,为什么还要使用位运算符?
但是为什么要在简单的乘法上使用它呢?是不是更快?

BITD,编译器没有那么智能,所以它通常更快。 @that other guy

今天,除非您的情况另有说明(例如,使用弱编译器),否则为清晰起见编写代码。无论哪种方式,一个好的编译器都会产生高效的代码。

hash = ((hash << 5) + hash) + tolower(c);
// or
hash = hash * 33u + tolower(c);

因为这是一个哈希,所以两者都一样清楚。


迂腐

如果c &lt; 0islower() 的定义不是很好。

替代方案,对安静的迂腐警告进行一些强制转换,并且可能会加快 unsigned 代码。

unsigned hash(const char *word) {
    const unsigned char *uword = (const unsigned char *) word;
    unsigned long hash = 5381u;
    int c;
    while ((c = *uword++)) 
        hash = hash*33u + (unsigned)tolower(c);
    }
    return (unsigned) (hash % N);
}

【讨论】:

    猜你喜欢
    • 2013-11-22
    • 2011-12-15
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 2015-05-17
    • 2018-05-12
    • 1970-01-01
    相关资源
    最近更新 更多