均匀分布的哈希函数

时间:2010-09-28 19:47:14

标签: algorithm random hash

我需要一个哈希函数,它将一些(例如2或3)无符号整数作为输入,并返回介于-1和+1之间的浮点值。

必须均匀分布这些返回值的集合。即使输入数字是连续的,函数的输出序列也必须是随机序列。 而且越快越好,我称之为很多次。

我希望这不是太多问:S ......

2 个答案:

答案 0 :(得分:4)

Murmurhash是一个非常好的(强大的)快速哈希函数,它已经对它进行了一些严格的测试。

http://sites.google.com/site/murmurhash/

虽然它本身并不专用于整数,但可以快速调整它。我有这样一个替代的表达方式,如果你的话没有在记忆中显示出来,那么你可能会更方便:

#define MURMURHASH2A_R 24
#define MURMURHASH2A_MULTIPLIER 0x5bd1e995
#define MURMURHASH2A_SEED 2166136261U  // No seed suggested, so using FNV32_OFFSET_BASIS
#define murmurhash2a_init(h) do { h = MURMURHASH2A_SEED; } while (0)
#define murmurhash2a_update(h,word)                     \
do {                                                    \
  u_int mmh2ak = (word) * MURMURHASH2A_MULTIPLIER;      \
  mmh2ak ^= mmh2ak >> MURMURHASH2A_R;                   \
  mmh2ak *= MURMURHASH2A_MULTIPLIER;                    \
  h *= MURMURHASH2A_MULTIPLIER;                         \
  h ^= mmh2ak;                                          \
 } while (0)
#define murmurhash2a_final(h)                   \
do {                                            \
  h ^= h >> 13;                                 \
  h *= MURMURHASH2A_MULTIPLIER;                 \
  h ^= h >> 15;                                 \
 } while (0)

u_int hash;
murmurhash2a_init(hash);
murmurhash2a_update(hash,firstint);
murmurhash2a_update(hash,secondint);
[...]
murmurhash2a_final(hash);

显然这是0-2 ^ 32-1。 murmurhash网站上有一个64位版本。将整数转换为范围内的浮点数留给读者的练习(分组)。

答案 1 :(得分:3)

您可以为此类任务采用标准方案:(a0 + Q*a1 + Q^2*a2 + Q^3*a3 + ...) % M其中M是一个非常大的素数,Q是您选择的系数。
在范围[0, M)中有足够随机的哈希值后,将其转换为浮点数[-1, 1]是微不足道的。

或者你可以删除% M并允许整数溢出发生,虽然我不确定它是多么安全(从“均匀分布”的角度来看)。

即使输入数字是连续的,函数的输出序列也必须是随机序列。
为此,您可以在表达式中使用ai而不是ai*ai。无论如何,这是Java中的简单实现。

double hash(int... a) {
    int Q = 433494437;
    int result = 0;
    for (int n : a) {
        result = result * Q + n * n;
    }
    result *= Q;
    return (double) result / Integer.MIN_VALUE;
}

即使连续数字,输出看起来也是随机的。您还可以使用64位整数来获得更高的精度。