是否反复向随机数生成器播种一个合理的哈希函数
Is repeatedly seeding a random number generator a reasonable hash function?
我希望生成大量随机数据,这些数据对于给定的key
是可重复的,包括数字列表:
[a, b, c, d, e, ...]
下面是一个好的或明智的方法来让RNG进入生成随机数据的状态,以这样的方式,对于每个n元组[a, b, c, ..., n]
,该数据与"相邻"n元组[a+1, b, c, ..., n]
, [a, b+1, c, ..., n]
等的输出不相关。
srand(a);
srand(rand() * b);
srand(rand() * c);
...
srand(rand() * n);
# generate random data:
for (int i=0; i < 100; +i)
printf("%d", rand());
我认为这个问题归结为以下内容:rand_hash
是2元组(a, b)
的好哈希函数吗?
int rand_hash(int a, int b) {
srand(a);
srand(rand() * b);
return rand();
}
注:我并不想暗示srand
和rand
是RNG的任何特定实现。为了便于讨论,假设我们使用的是一个很好的梅森扭转码。
Edit:如果不清楚的话,"合理的哈希函数"是指以下内容。在二元组[a, b]
的限制情况下,rand_hash
的输出应该在int
的范围内是一致的,并且(通常)a
或b
的变化幅度与返回值的变化幅度之间不应该存在相关性。
不,这不是一个合理的方法。
- 你不知道
rand
的实现是什么。随机数生成器的设计目的是在几个生成的随机数的周期内提供近似均匀分布的数字。它们不是为了在一组(32位)种子上提供均匀分布的数字而设计的。在您假设的mersenne_twister
的情况下,随机数生成器的状态比您提供给srand
(特别是624*sizeof(int)
)的整数大得多。RNG确保其输出是随机和均匀的大部分能力都来自于那个额外的状态,而你拿走了它。(种子只能是2^32个状态中的一个) - 如果你曾经升级你的编译器或库或类似的东西,任何你可能已经序列化到磁盘将变得不可读。(如果
rand
是一个黑盒,没有人说明天的实现与今天的实现匹配)。 - 对于相同的
srand
输入,哈希函数的输出返回相同的东西。因此,您已经有了一个散列——srand
的输入。对于给定的srand
输入,RNG生成相同的输出。因此,您可能获得的哈希数不大于返回您已经计算过的哈希值。如果您的初始散列到srand的散列对于散列表来说分布不好,那么请适当地扩展散列,以便它在您的表中表现良好。 -
对于
rand
的一些实现,这执行得非常差。考虑一个线性同余生成器(这在C库中更常见,因为它的状态为sizeof(int)
——例如BSD生成器)。LCG的格式为xNext = a*xCurrent + b
。考虑:static int seed = 0; void srand(int newSeed) { seed = newSeed; } int rand() { seed = (int) ((1103515245 * ((unsigned int)seed) + 12345) & 0x7fffffffUL); return seed; }
请注意,这种(常见)类型的生成器生成的哈希值很容易与您的输入值相关联。
如何使用boost::hash_combine
http://www.boost.org/doc/libs/1_33_1/doc/html/hash_combine.html创建您的初始种子?使用srand
不止一次总是在我的脑海中触发危险信号。
潜在问题:
如果另一个线程在你的哈希函数中间调用rand()
怎么办?
相关文章:
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何仅为一个函数添加延迟
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 我需要将多个函数组合为一个函数
- 在C++中声明一个函数时,它需要有函数本身的参数吗
- 如何创建一个函数来计算并返回平均值、最大值和最小值
- 一个函数,用于查找字符串1包含字符串2 c++的次数
- 如何将一个类的函数作为另一个类的另一个函数的参数传递
- 编写一个函数以使用 n 百分比的 CPU 使用率
- 将 N-arg 函数包装到另一个函数中
- 如何封装一个函数,以便它只能由同一类中的一个其他函数调用?
- C++(.cpp文件和.h文件)拆分代码并添加一个函数,提取 - 这很容易吗?
- C++从另一个函数退出函数
- 编写一个函数来删除单链表中的节点(尾部除外),仅授予对该节点的访问权限
- 视觉我希望一个函数在另一个函数C++中进行计算
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 在另一个函数 (c++) 中调用变量
- 如何在另一个函数中使用返回值作为参数?
- 如何包装一个函数以适应另一个函数的所需类型
- 创建一个函数的 Python 绑定,返回指向带有 boost 的向量的指针