#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv) {
srand(time(NULL));
int r = rand();
printf("%d\n", r);
return (EXIT_SUCCESS);
}
当我在几秒钟的时间内重复运行此代码片段时,我得到了一系列增加的数字,例如213252683,213975384,214193875,214445980。在我看来,我只是打印出系统时间 - 当我添加行printf("%d\n", time(NULL))
时,似乎可以确认该假设;到代码。我究竟做错了什么?我在Mac OS X 10.6.1(Snow Leopard)上运行,但我只使用标准库功能,所以它不应该有所作为。谢谢!
答案 0 :(得分:3)
伪随机数生成为源自初始种子的混沌序列。 srand
通过设置此种子来初始化随机性。显然,序列中的第一个随机数是种子本身 - 这是您设置的time()
值。
这就是为什么生成随机序列的正确方法是在程序开始时只调用srand()
一次,然后只调用rand()
(好吧,也许直到序列)开始循环,这不应该太快发生,但这取决于生成函数)。正如您所见,过于频繁地调用srand()
会使随机性恶化。
答案 1 :(得分:1)
如果它有帮助我通常会这样使用它:
int rand_between(int min, int max)
{
static int flag = 1;
FILE *urandom;
unsigned int seed;
if (flag)
{
flag = 0;
if (!(urandom = fopen ("/dev/urandom", "r")))
fprintf(stderr, "Cannot open /dev/urandom!\n");
fread(&seed, sizeof(seed), 1, urandom);
srand(seed);
}
return ((int)rand() % (max - min)) + min;
}
获取随机大写字母:
char letter = (char)rand_between('A', 'Z');
答案 2 :(得分:0)
当我在几秒钟内重复运行此代码片段时, 我得到了一系列越来越多的数字,比如213252683,213975384, 214193875,214445980。
我无法重现这一点。在我的系统(Debian Linux)上,我得到了没有订购的数字。此外,结果与您在打印time(NULL)
时获得的结果不同。
这应该是这样的:您正在使用当前时间(以秒为单位)为随机数生成器播种。因此,只要时间(低至秒)相同,程序就会打印相同的结果。
我做错了什么?
嗯,这取决于你想要什么。如果你想要每次运行的随机数,你需要一个更好的随机源。您可以尝试gettimeofday
等具有更高分辨率的函数(我相信通常为ms)。此外,混合使用其他随机来源,例如您的流程ID。
在大多数程序中,您看到的效果没有问题,因为通常只在开始时调用srand()
,然后rand()
会在每次调用时返回不同的数字。
如果你想要“安全”(即不可预测的)随机数,那就是另一个游戏。参见例如Wikipedia了解概述。
答案 3 :(得分:0)
随机数发生器差别很大,因此很难在其他机器上重现。看起来您实现的第一个数字只是种子值。例如,在我的情况下,第一个数字似乎与种子线性相关。通常,您将在程序中调用srand
一次,并在rand
调用多次,并且连续调用将获得更随机的结果。如果你想避免这个问题,那么做是合理的:
srand(time(NULL));
rand();
int r = rand();
printf("%d\n", r);
第一个rand
调用确保种子不会返回,下一个应该选择看起来更随机的内容。请注意,如果您在足够短的时间跨度内运行程序两次(两次运行中time(NULL)
相同),您将得到完全相同的结果。这绝对是预期的 - 如果这是一个问题,使用不同的种子值(pid + time
可能是一个好的开始,或者只是一个更高分辨率的时间)。
答案 4 :(得分:0)
你应该使用random()而不是rand()。它在各方面都优于rand(),它也包含在stdlib中。
请尝试以下代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int r = random();
printf("%d\n", r);
return (EXIT_SUCCESS);
}