boost hash为不同的输入返回相同的值

时间:2013-05-02 21:04:17

标签: c++ boost hash

我有两个对象,即Account和Transaction,其中Transaction是唯一的Account对和递增的id号。我想使用boost :: hash来获取这些值的唯一值,并按照说明重载了hash_value方法:http://www.boost.org/doc/libs/1_53_0/doc/html/hash/custom.html

class Account {
  ...
};

class Transaction
{
    Account account;
    unsigned int id;
};

帐户的hash_value方法正常工作,并且返回的值对于给定帐户始终是唯一的,但是要创建唯一对,Transaction的方法需要使用哈希 _combine(按照提升的说明):

inline std::size_t hash_value( const Account& acct )
{
    boost::hash<int> hasher;
    size_t rval = hasher( acct.id() ); //just an int. guaranteed to be unique
    return rval;
}


inline std::size_t hash_value( const Transaction& t )
{
    std::size_t seed = 0;
    boost::hash_combine( seed, t.account );        
    boost::hash_combine( seed, t.id );

    return seed;
}

有时会返回不同输入的相同值。为什么??我只有几千个账户,而且身份证号码只有几十万。这似乎不是一个上限问题。

有谁知道这是一个bug,还是我需要播种boost hash?

由于

2 个答案:

答案 0 :(得分:5)

查找完美的哈希和生日悖论,并且为了完整性,我们要找到鸽子原则。

它归结为散列函数通常会产生冲突,除非您正在散列的内容具有您已利用的非常特定的属性。你看到任何给定键集的哈希冲突的可能性都是违反直觉的,因为这是我们没有接线的数学现实之一:获得任何特定哈希的1/365机会,你的几率是只有23把钥匙,碰撞是50/50。

答案 1 :(得分:1)

Boost提供了良好的通用散列函数,因为它对输入没有/很少有假设,并试图加快速度。在大多数情况下,您可以对输入做出特定的假设,以创建比从boost获得的更好的哈希函数。例如,您可以通过假设字符串包含英文文本来优化字符串哈希函数。通过使用假设,您可以制作更好的散列函数(如:更少的碰撞)。例如,如果你需要合并两个哈希值,每个哈希值都是1到1000之间的整数,很明显你不会得到冲突,你可以将其中一个乘以1000然后再加上另一个。

编写自定义哈希函数时要非常小心,因为除了出错之外还有一个明显的缺点:代码健壮性总是受到影响

示例1:您为英语字符串优化UTF-8字符串哈希。突然,应用程序获得了中文字符串。

示例2:您假设ID始终很小,因为ID从1开始,每次分配ID时增加1,并且分配的数量永远不会超过几千。现在有人将id更改为随机GUID。