为什么这个数字不是随机的?

5

以下是一段代码示例:

#include<stdlib.h>
#include<stdio.h>

int main()
{
    int x;
    x = rand()%100;
    printf("The Random Number is: %i", x);

return 0;
}

它似乎总是将随机数打印为83。为什么会这样?

1
因为您没有初始化 PRNG。您需要基于某些变化的东西设置种子,例如时间。但我建议完全避免集成的 C PRNG。 - CodesInChaos
@CodeInChaos:'PRNG'是什么?你在这里跟一个完全的C语言新手交谈。 - jones
我只想再次强调,大多数rand的实现非常糟糕,甚至在简单的模拟中都会崩溃。 - CodesInChaos
6个回答

6

大多数随机数生成器都是可重复的。在使用之前,您需要为生成器提供种子,通常使用系统时间来完成。

#include <time.h>
srand(time(NULL));

3
注意,从时间初始化伪随机数生成器并不总是可行的:这会给你一个可预测的种子。特别是,加密需要不可预测的随机数,但 C 库无法提供它们。 - Gilles 'SO- stop being evil'
1
请注意,在高度线程化的系统(如Web服务器)上仅使用时间往往会失败,因为两个不同的线程可能同时运行(在time()的精度范围内)。 - Sklivvz

6

必须引用 XKCD 段子:

enter image description here

作为人们所说的,您需要正确地种子伪随机数生成器。
问题在于,它仍然只生成伪随机数。大多数“真正”的随机数发生器需要访问某些物理现象,这些物理现象是自然随机的(例如,时钟偏差或温度波动)。
否则,XKCD参考并不离真相太远。Dilbert也是如此。

enter image description here


谢谢,我喜欢流行文化的参考! - jones
@jones:不用谢!一旦你开始研究随机数,就会发现它们是一个棘手的问题。xkcd和Dilbert漫画显然知道这一点,并在早期划定了界限。 :-) - Peter K.
@downvoter:为什么?毫无解释地进行投票——充其量是粗鲁的,或者在我看来是懦弱的。就我所知,我的帖子中没有任何不诚实或未回答问题的地方(http://stackoverflow.com/faq)。 - Peter K.

4
由于 rand 使用的伪随机数生成器始终使用相同的种子进行初始化。
为了使用不同的种子进行初始化,您可以使用 srand 函数,并将其初始化为例如 srand(time(NULL))

3

因为83是一个随机数,不是吗?

更严肃地说,拥有提供可重复行为的程序非常有用,因此如果您不更改种子,则rand始终返回相同的数字序列。


2
有一个很好的理由,解释为什么你并不总是想要随机的随机数! - Oliver Charlesworth

1
通过包含 <time.h> 并调用 srand(time(0)); 来初始化随机数生成器(感谢我的评论者提供的意见)。

@R. Time的类型是time_t。虽然它通常是无符号整数,但我不认为这是保证的。 - jonsca
2
@jonsca:time_t保证是算术类型,因此它将被转换为正确的类型。(如果time_t允许是其他类型,则强制转换将无效,因此无论如何都是无用的。) - Gilles 'SO- stop being evil'
@Gilles 我以前总是收到警告,但出于某种原因它们没有弹出。我得研究一下。感谢您发表实际声明。 - jonsca
3
在 C 语言中,强制类型转换的经验法则是:如果编译器发出警告,而添加一个强制类型转换可以消除该警告,那么你只是修复了表面问题,而没有解决根本问题。在大多数需要使用强制类型转换的情况下,编译器并不智能地提供警告提示。 - Gilles 'SO- stop being evil'
原则上,这可能是未定义的行为,无论是否有强制转换,因为 time_t 允许是浮点类型,并且当前时间的值可能太大而无法适合 unsigned int 中。因此,正如Gilles所说,编译器在强制转换时抑制的任何警告可能实际上正在告诉您某些理论上重要的事情,例如,您的代码将在某个期限停止工作。不可否认,在Unix纪元和32位int中,该截止日期为2106年,因此可能没有太多实际利益... - Steve Jessop
显示剩余4条评论

0

除非你的随机数生成器可以访问彼得早期引用的真正随机物理现象,否则无法生成真正随机的随机数。但是,对于一般用途,您可以使用C标准库函数来生成随机数。以下是生成两个限制(最大值和最小值)之间的随机数的示例代码:

#include<stdio.h>
#include<stdlib.h>

#define MIN 1
#define MAX 5
#define QUANTITY 5

int main()
{
     int i;
     //stores the time in seconds
     time_t seconds;
     //getting the system time
     time(&seconds);
     //initializing the random generator with system time
     //as the seed value
     srand((long)seconds);

     for(i = 0; i < QUANTITY; i++)
     {
           printf("%f\t",((float)rand())/RAND_MAX*(MAX-MIN)+MIN);
     }
     printf("\n");

     return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接