【发布时间】:2010-09-28 19:47:14
【问题描述】:
我需要一个哈希函数,它需要几个(例如 2 或 3 个)无符号整数作为输入,并返回一个介于 -1 和 +1 之间的浮点值。
这些返回值的集合必须均匀分布。函数的输出序列必须看起来是随机序列,即使输入数字是连续的。 而且越快越好,我经常这样称呼它。
我希望这不是太多要求:S...
【问题讨论】:
我需要一个哈希函数,它需要几个(例如 2 或 3 个)无符号整数作为输入,并返回一个介于 -1 和 +1 之间的浮点值。
这些返回值的集合必须均匀分布。函数的输出序列必须看起来是随机序列,即使输入数字是连续的。 而且越快越好,我经常这样称呼它。
我希望这不是太多要求:S...
【问题讨论】:
Murmurhash 是一个非常好(强大)且快速的哈希函数,已经对其进行了一些严格的测试。
http://sites.google.com/site/murmurhash/
虽然它本身并不专用于整数,但可以快速调整它以实现这一点。如果您的单词没有按顺序排列在记忆中,我有这样一个替代表述可能对您更方便:
#define MURMURHASH2A_R 24 #define MURMURHASH2A_MULTIPLIER 0x5bd1e995 #define MURMURHASH2A_SEED 2166136261U // 没有种子建议,所以使用 FNV32_OFFSET_BASIS #define murmurhash2a_init(h) 做 { h = MURMURHASH2A_SEED; } 而 (0) #define murmurhash2a_update(h,word) \ 做 { \ u_int mmh2ak = (word) * MURMURHASH2A_MULTIPLIER; \ mmh2ak ^= mmh2ak >> MURMURHASH2A_R; \ mmh2ak *= MURMURHASH2A_MULTIPLIER; \ h *= MURMURHASH2A_MULTIPLIER; \ h ^= mmh2ak; \ } 而 (0) #define murmurhash2a_final(h) \ 做 { \ h ^= h >> 13; \ h *= MURMURHASH2A_MULTIPLIER; \ h ^= h >> 15; \ } 而 (0) u_int 哈希; murmurhash2a_init(哈希); murmurhash2a_update(hash,firstint); murmurhash2a_update(hash,secondint); [...] murmurhash2a_final(哈希);显然这是返回 0-2^32-1。 murmurhash 网站上有一个 64 位版本。在一定范围内将整数转换为浮点数作为练习(除法)留给读者。
【讨论】:
您可以为此类任务采用标准方案:(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 位整数以获得更高的精度。
【讨论】:
(-1), (0), (1),结果确实不是随机的。供电到 3 或类似 (n + 12345) * n 可能会做得更好。