C++ 中是不是有任何函数可以计算保证至少 64 位宽的字符串的指纹或散列?

Posted

技术标签:

【中文标题】C++ 中是不是有任何函数可以计算保证至少 64 位宽的字符串的指纹或散列?【英文标题】:is there any function in C++ that calculates a fingerprint or hash of a string that's guaranteed to be at least 64 bits wide?C++ 中是否有任何函数可以计算保证至少 64 位宽的字符串的指纹或散列? 【发布时间】:2009-05-25 22:12:34 【问题描述】:

C++ 中是否有任何函数可以计算保证至少 64 位宽的字符串的指纹或哈希?

我想用unordered_map<long long, int> 替换我的unordered_map<string, int>

鉴于我得到的答案(感谢 Stack Overflow 社区...),我所描述的技术并不为人所知。我想要一个无序的指纹图而不是字符串的原因是为了空间和速度。第二个映射不必存储字符串,并且在进行查找时,它不会导致任何额外的缓存未命中来获取这些字符串。唯一的缺点是碰撞的可能性很小。这就是为什么密钥必须是 64 位的原因:2^(-64) 的概率基本上是不可能的。当然,这是基于一个好的哈希函数,这正是我的问题所寻求的。

再次感谢 Stack Overflowers。

【问题讨论】:

64 位还是 128 位?你的问题有点模棱两可。 请记住,std::string 对象不包含字符串数据——它包含指向包含字符串数据的动态内存的指针。因此,您关于将字符串存储在哈希表中会减慢速度的断言可能是错误的。 @BillyONeal:它会减慢速度,因为进行比较需要与动态内存进行比较,这意味着缓存未命中。 @Stefan,我已经删除了我询问 128 位类型的第二个问题。 @Whoever 否决了这个问题。为什么这是一个坏问题?我解释了我想做什么以及为什么。 【参考方案1】:

unordered_map 始终将密钥散列到 size_t 变量中。这与密钥的类型无关,完全取决于您使用的架构。

【讨论】:

我在查看文档时注意到了这一点。但是,如果不能保证 size_t 为 64 位或更多位,那么我仍然必须存储字符串,因为我不能完全确定不会发生冲突。 可惜size_t不是std::hash的模板参数。【参考方案2】:

c++ 没有原生 128 位类型,也没有原生散列支持。这种散列扩展应该添加到 TR1 中,但据我所知,我的许多编译器不支持 128 位整数。 (Microsoft 支持 __int128 类型——不过仅在 x64 平台上)

我希望 unordered_map 包含的函数在任何情况下都会更快。

如果你真的想这样做,MD5 提供了一个很好的 128 位哈希。

【讨论】:

【参考方案3】:

如果要将任何字符串映射到唯一的整数:

typedef std::map<string,long long> Strings;
static Strings s_strings;
long long s_highWaterMark = 0;
long long my_function(const string& s)

  Strings::const_iterator it = s_strings.find(s);
  if (it != s_strings.end())
  
    //we've previously returned a fingerprint for this string
    //now return the same fingerprint again
    return it->second;
  
  //else new fingerprint
  long long rc = ++s_highWaterMark;
  //... remember it for next time
  s_strings.insert(Strings::value_type(s, rc));
  //... and return it this time
  return rc;

【讨论】:

不错的解决方案。太糟糕了,没有内置的哈希函数。这样做的重点是优化空间和速度,与就地计算哈希值相比,额外的查找在缓存未命中方面的成本很高。 我认为您应该寻找一个产生唯一映射的哈希函数。而是寻找一个产生通常唯一映射的散列函数,并在可能但罕见的发生碰撞的情况下对您的映射执行其他操作(例如线性搜索)。【参考方案4】:

您想要实现的具体目标是什么?使用“更大”的哈希函数,您的地图不会更好地工作。无论如何,并不显着。

【讨论】:

哈希表会小很多,因为它不需要存储字符串。 另外,查找会更快,因为它不会导致在哈希表中加载字符串时缓存未命中。 (另外,这不是一个“答案”。)

以上是关于C++ 中是不是有任何函数可以计算保证至少 64 位宽的字符串的指纹或散列?的主要内容,如果未能解决你的问题,请参考以下文章

C 或 C++ 链接器中是不是有任何类型检查?

C++ 中是不是有任何与传输无关的 JSON-RPC 实现? [关闭]

C++ 的新操作是不是可以保证地址返回的对齐?

MS Visual Studio 2010 C++ 预处理器 - 如果函数在宏中定义并在其他地方调用,未定义时是不是有任何开销

是否有任何函数可以从标准输入中获取无限的输入字符串

在没有 new 的情况下在 C++ 中调用构造函数