1

可能重复:
为什么我总是用 rand() 得到相同的随机数序列?

我一直在尝试在 C 中生成随机数,但遇到了一些奇怪的事情。我不知道它是否仅在我的编译器上,但是每当我尝试使用 rand() 函数生成伪随机数时,它都会返回一个非常可预测的数字——确切地说是使用之前的参数生成的数字加上 3.125。很难解释,但这里有一个例子。

srand(71);
int number = rand();
printf("%d", number);

这将返回 270。

srand(72);
int number = rand();
printf("%d", number);

这将返回 273。

srand(73);
int number = rand();
printf("%d", number);

这将返回 277。

srand(74);
int number = rand();
printf("%d", number);

这将返回 280。

每八分之一数字高4。否则为3。

这不可能是对的。我的编译器有问题吗?

编辑:我想通了——我创建了一个函数,我只播种一次,然后循环rand()它并生成随机数。谢谢你们!

4

4 回答 4

3

这里的困惑在于伪随机数生成器是如何工作的。

像 C 那样的伪随机数生成器rand通过一个代表当前“状态”的数字来工作。每次rand调用该函数时,都会对“状态”编号进行一些确定性计算,以生成下一个“状态”编号。因此,如果给定生成器相同的输入(相同的“状态”),它将产生相同的输出。

因此,当您使用 为生成器播种时srand(74),它每次都会生成相同的数字串。当您使用 为生成器播种时srand(75),它将生成不同的数字字符串等。

确保每次输出不同的常用方法是始终提供不同的种子,通常通过以秒/毫秒为单位的当前时间播种生成器来完成,例如srand(time(NULL))

编辑:这是一个演示此行为的 Python 会话。这是完全可以预料的。

>>> import random

如果我们给生成器播种相同的数字,它总是会输出相同的序列:

>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]

如果我们给它一个不同的种子,即使是稍微不同的种子,数字将与旧种子完全不同,但如果使用相同的(新)种子,数字仍然相同:

>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]

我们如何让我们的程序每次都有不同的行为?如果我们提供相同的种子,它的行为总是相同的。我们可以使用这个time.time()函数,每次调用它都会产生一个不同的数字:

>>> import time
>>> time.time()
1347917648.783
>>> time.time()
1347917649.734
>>> time.time()
1347917650.835

因此,如果我们继续通过调用 重新播种它time.time(),我们每次都会得到不同的数字序列,因为种子每次都不同:

>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[60, 75, 60, 26, 19, 70, 12, 87, 58, 2, 79, 74, 1, 79, 4, 39, 62, 20, 28, 19]
>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[98, 45, 85, 1, 67, 25, 30, 88, 17, 93, 44, 17, 94, 23, 98, 32, 35, 90, 56, 35]
>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[44, 17, 10, 98, 18, 6, 17, 15, 60, 83, 73, 67, 18, 2, 40, 76, 71, 63, 92, 5]

当然,比不断地重新播种更好的是播种一次并从那里继续:

>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[94, 80, 63, 66, 31, 94, 74, 15, 20, 29, 76, 90, 50, 84, 43, 79, 50, 18, 58, 15]
>>> [random.randint(0, 100) for _ in xrange(20)]
[30, 53, 75, 19, 35, 11, 73, 88, 3, 67, 55, 43, 37, 91, 66, 0, 9, 4, 41, 49]
>>> [random.randint(0, 100) for _ in xrange(20)]
[69, 7, 25, 68, 39, 57, 72, 51, 33, 93, 81, 89, 44, 61, 78, 77, 43, 10, 33, 8]
于 2012-09-17T20:50:22.337 回答
0

rand()伪随机数生成器实现。

连续调用产生的数字的分布rand()具有随机数的性质,但顺序是预先确定的。“开始”编号由您提供的种子决定。

您应该只给 PRNG 一个种子。为其提供多个种子可以从根本上改变生成器的随机性。此外,一遍又一遍地为其提供相同的种子会消除所有随机性。

于 2012-09-17T20:51:34.387 回答
0

每次调用都会rand()返回预定义序列中的下一个数字,其中起始数字是提供给 的种子srand()。这就是为什么它被称为随机数生成器,而不是随机数生成器。

于 2012-09-17T20:49:43.733 回答
0

无论实现如何,生成“随机”数取决于发散的无限序列。无限序列是使用随机函数的种子生成的,由于其性质,它实际上是伪随机的。这将向您解释为什么您的数字实际上非常依赖于您提供函数的种子。

在一些实现中,序列只有一个并且种子是序列的起始成员。在其他情况下,取决于种子,存在不同的序列。如果未提供种子,则种子由内部“时钟”确定。

randValue % upperBound通过分别执行和为您的随机数使用上限和下限时,该数字将被截断randValue + lowerBound随机实现与哈希函数非常相似。根据体系结构,随机值的上限取决于它可以执行的最大整数/双精度值,如果用户未将其设置得更低。

于 2012-09-17T21:54:44.800 回答