关于C#:srand与rand函数有什么关系?

How does srand relate to rand function?

我知道rand()函数会生成相同的编号,如果不更改种子编号,则每次运行它时都会生成相同的编号。srand()就是在这里出现的。时间总是在变化,所以我知道您应该将时间(空)参数传递给srand。我的问题是关于一个教程站点下面的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
    int i, n=5;
    time_t t;

    /* Intializes random number generator */
    srand((unsigned) time(&t));

    /* Print 5 random numbers from 0 to 50 */
    for( i = 0 ; i < n ; i++ ) {
        printf("%d
"
, rand() % 50);
    }

    return(0);
}

我看不到SRAND的链接

1
((unsigned) time(&t));

还有兰德。

1
2
printf("%d
"
, rand() % 50);

兰德和SRAND之间的联系在哪里?我的意思是或期望是,我假设rand()将从srand()获得一些参数,这样它就知道每次生成不同的数字。我假设它看起来像rand(srand(time(null));

就像初始化一个变量而不使用它。srand正在初始化,但我看不到它正在使用。

兰德公司是否会产生不同的数字,因为SRAND在兰德公司之前被称为第一个?


随机数种子是一个全局静态变量。randsrand都可以访问它。


srand()设置rand用来生成"随机"数的种子(在引号中,因为它们通常是伪随机的)。如果你在第一次打电话给rand之前没有打电话给srand,就好像你打电话给srand(1)把种子设为1。

许多代码使用当前时间作为种子,以便使每个程序运行时使用不同的随机数序列,但为了重复性的目的,您可以在调试期间将其更改为类似于srand(42)的序列。对time()的调用实际上不需要一个变量来放置时间,您只需传递NULL即可:

1
srand (time (NULL));

整个过程可以在一个单独的文件中实现,类似于标准(ISO C99 7.20.2.2 The srand function中给出的示例)。

1
2
3
4
5
6
7
// RAND_MAX assumed to be 32767.
static unsigned long int next = 1;
void srand(unsigned int seed) { next = seed; }
int rand(void) {
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

next是文件顶部的静态变量,这意味着它对文件外部的所有内容都不可见,但对文件内部的所有内容都可见(类似于局部全局)。这就是srand()rand()之间的通信方式。


你看不到链接,因为(幸运的是!)设计rand()的人决定保留实现细节,就像你看不到FILE中来自stdio的内容一样;缺点是他们决定使该状态成为全局(但隐藏)变量,而不是生成器的参数。

与不推荐使用的rand_r()相反:状态是无符号整数(假定大于等于32位),这意味着即使是禁止使用状态大于该值的任何更好的生成器,也只是因为没有存储空间!

相反,通过隐藏内部状态,您可以自由选择任何最有效的算法(速度、周期等),并在幕后使用它,只要您保证在不初始化的情况下调用rand与在seed==1的情况下调用srand相同。

paxdiablo向您展示了C标准中的示例;请参见http://en.wikipedia.org/wiki/multiply-with-carry,以获取使用可以隐藏在rand/srand后面的不同生成器的示例。

更清楚一点:如果rand_r设计得当,就会有一个不透明的类型,比如rand_t(可以是一个整数、一个结构、一个数组,…),你可以把它传递给rand_r和一些下位的srand_r,如

1
2
3
rand_t state;
srand_r(&state, 1);
n = rand_r(&state);

rand函数与此完全相同,只是只有一个state变量。


兰德给你一个伪随机的数字序列。

这个数字是由一个算法生成的,该算法每次调用它时都返回一个明显不相关的数字序列。该算法使用一个种子来生成序列,该序列应使用函数srand初始化为一些独特的值。

srand在每次调用时都会将指针设置到您要进入的列表中的某个位置。如果你不每次尝试都调用它,或者给它一个固定种子,它会给你相同的序列。很多人建议把当前的第二个作为种子。但是,如果您尝试在同一秒中运行代码两次,它将为您提供相同的顺序。

对于调用srand时使用的每个不同的seed值,可以期望伪随机数生成器在随后调用rand时生成不同的结果序列,以供进一步解释。