【问题标题】:Why can a hash such as djb2, when used with a ulong, be larger than 32 bits为什么像djb2这样的hash,与ulong一起使用时,会大于32位
【发布时间】:2021-10-22 23:12:35
【问题描述】:
unsigned long hash(char *str) 
{
    unsigned long hash = 5381;
    int c;
    while ((c = *str++))
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    return hash % NUM_BUCKETS;
}

使用此代码,当您在函数中输入 20 个字母(例如 zzzzzzzzzzzzzzzzzzzzzzzzzzzz)时,您会得到一个巨大数字的输出。如果限制为仅 32 位,long 如何保存数字?

【问题讨论】:

  • you get an output of a huge number 您如何准确地检查输出的大小? printf(what here?)?
  • 这能回答你的问题吗? djb2 Hash Function

标签: c hash bit


【解决方案1】:

您应该首先检查unsigned long 32 位。如果您获得的值超过(大约)42 亿,那么几乎可以肯定它比这更宽(a)

您可以通过编译和运行以下程序来检查

#include <limits.h>
#include <stdio.h>

int main(void) {
    printf("%d\n%zu\n", CHAR_BIT, sizeof(unsigned long));
    return 0;
}

第一个值是字节中的位数,第二个值是unsigned long 中的字节数。因此,将两者相乘将得到unsigned long 类型中的位数。

在我的系统上,我得到 88,表示 64 位大小。


(a) ISO C 标准没有规定 C 中原始类型的确切大小(尽管它可能适用于 uint32_t 之类的东西)。事实上,它甚至根本没有直接规定位数。

什么是任务是最小范围要求,对于unsigned long0..4294967295(我之前提到的42亿)。

但是,一个实现可以免费为您提供更大的东西,例如 128 位类型,它可以为您提供从零到大约 1038 或一亿的范围百万百万。

顺便说一句,我本可以使用了数十亿、数万亿甚至数亿,但是:

  • 有时对于它们所代表的十的实际幂存在分歧;和
  • 许多“百万”后缀的使用比单个很少知道的后缀(如“undecillion”或“sextillion”)更大。

【讨论】:

    【解决方案2】:

    unsigned long 至少 32 位,但它可以更大。它是一种 64 位类型,大多数编译器在大多数 64 位处理器上运行,Windows 除外。所以返回 unsigned long 的函数可以返回大于 232 的值。

    但是,您显示的函数保证返回一个范围从 0NUM_BUCKETS 的数字。如果您看到大于NUM_BUCKETS 的值,则您看到的不是此函数返回的值。也许您的代码中有错误。确保你已经在你的编译器上启用了所有合理的警告并且你已经正确地解决了它们(而不是盲目地添加强制转换)。如果您仍然不了解程序的输出,请使用调试器并检查中间值。如果你仍然不明白你的程序在做什么,你可以在线提问,complete code that reproduces the problem

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-29
      • 2012-11-28
      相关资源
      最近更新 更多