在C中生成随机数

在search关于在CI中生成随机数的教程时发现了这个主题

当我尝试使用不带参数的rand()函数时,我总是得到0.当我尝试使用带有参数的rand()函数时,我总是得到值41.每当我尝试使用arc4random()random()函数,我得到一个LNK2019错误。

以下是我所做的:

 #include <stdlib.h> int main() { int x; x = rand(6); printf("%d", x); } 

这段代码总是生成41.我在哪里出错? 我正在运行Windows XP SP3并使用VS2010命令提示符作为编译器。

在调用rand来初始化随机数发生器之前,您应该调用srand()。

要么用一个特定的种子来调用它,而且你总会得到相同的伪随机序列

 #include <stdlib.h> int main () { srand ( 123 ); int random_number = rand(); return 0; } 

或者用变化的来源,即时间函数来调用它

 #include <stdlib.h> #include <time.h> int main () { srand ( time(NULL) ); int random_number = rand(); return 0; } 

响应Moon的评论 rand()生成一个0和RAND_MAX(在stdlib.h中预先定义的一个macros)之间具有相等概率的随机数,

然后,您可以将此值映射到更小的范围,例如

 int random_value = rand(); //between 0 and RAND_MAX //you can mod the result int N = 33; int rand_capped = random_value % N; //between 0 and 32 int S = 50; int rand_range = rand_capped + S; //between 50 and 82 //you can convert it to a float float unit_random = random_value / (float) RAND_MAX; //between 0 and 1 (floating point) 

这对于大多数用途来说可能是足够的,但是它的值得指出的是,在第一种情况下,如果N不能均等地分配到RAND_MAX + 1,则使用mod运算符会引入轻微的偏差。

随机数发生器是有趣和复杂的,广泛地说,C标准库中的rand()生成器不是一个高质量的随机数生成器,阅读(定义http://en.wikipedia.org/wiki/Random_number_generation)的质量)。;

http://en.wikipedia.org/wiki/Mersenne_twister (来源http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html )是一种stream行的高质量随机号码发生器。

此外,我不知道arc4rand()或随机(),所以我不能评论。

您需要播种您的PRNG,以便每次都以不同的值开始。

一个简单但低质量的种子是使用当前时间:

 srand(time(0)); 

这会让你开始,但被认为是低质量 (例如,如果你正在尝试生成RSA密钥,不要使用它)。

背景。 伪随机数发生器不会创build真正的随机数字序列,只是模拟它们。 给定起点号码,PRNG将始终返回相同的数字序列。 默认情况下,它们以相同的内部状态开始,所以会返回相同的顺序。

为了不相同的顺序,你改变了内部状态。 改变内部状态的行为被称为“播种”。

 #include <stdlib.h> int main() { int x; x = rand(6); printf("%d", x); } 

特别是作为一个初学者,你应该要求你的编译器打印每一个关于错误代码的警告。 现代编译器知道很多不同的警告,可以帮助您更好地编程。 例如,当你用GNU C编译器编译这个程序时:

 $ gcc -W -Wall rand.c rand.c: In function `main': rand.c:5: error: too many arguments to function `rand' rand.c:6: warning: implicit declaration of function `printf' 

你在这里得到两个警告。 第一个说randfunction只需要零参数,而不是你试图。 要获得0到n之间的随机数,可以使用expression式rand() % n ,这对于小n来说并不完美,但可以。 产生的随机数通常不是均匀分布的; 更小的值会更频繁地返回。

第二个警告告诉你,你正在调用编译器当时不知道的函数。 你必须通过说#include <stdio.h>来告诉编译器。 哪些function并不总是很简单,哪些包含文件是必需的,但在许多情况下,要求Open Group规范提供便携式操作系统: http : //www.google.com/search?q=opengroup+rand 。

这两个警告告诉你很多有关C编程语言的历史。 40年前,函数的定义并不包括参数的数量或参数的types。 调用一个在大多数情况下工作的未知函数也是可以的。 如果你想今天编写代码,你不应该依赖这些旧function,而是启用编译器的警告,理解警告,然后正确地修复它们。

另外,线性同余PRNG倾向于在较低位上的较高位上产生更多的随机性,因此为了覆盖结果,不使用模数,而是使用类似的东西:

 j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0))); 

(这个来自“C中的数值食谱”,第7章)

你首先需要种子发生器,因为它不会产生真正的随机数字!

尝试这个:

 #include <stdlib.h> #include <time.h> int main() { // random seed, time! srand( time(NULL) ); // hackish but gets the job done. int x; x = rand(); // everytime it is different because the seed is different. printf("%d", x); } 

或者,例如,要获得0到19范围内的伪随机int,可以使用像这样的更高位:

 j = ((rand() >> 15) % 20; 
 int *generate_randomnumbers(int start, int end){ int *res = malloc(sizeof(int)*(end-start)); srand(time(NULL)); for (int i= 0; i < (end -start)+1; i++){ int r = rand()%end + start; int dup = 0; for (int j = 0; j < (end -start)+1; j++){ if (res[j] == r){ i--; dup = 1; break; } } if (!dup) res[i] = r; } return res; }