在C中生成随机数

时间:2010-06-18 05:23:56

标签: c random

在搜索有关在C中生成随机数的教程时,我找到了this topic

当我尝试使用没有参数的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命令提示符作为编译器。

7 个答案:

答案 0 :(得分:31)

你应该在调用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中预先定义的宏)

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

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用于定义质量)。 / p>

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

另外,我不知道arc4rand()或random()所以我无法评论。

答案 1 :(得分:5)

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

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

srand(time(0));

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

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

要获得相同的序列,请更改内部状态。改变内部状态的行为称为“播种”。

答案 2 :(得分:3)

#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'

这里有两个警告。第一个说rand函数只接受零参数,而不是你尝试过的参数。要获得介于0和n之间的随机数,您可以使用表达式rand() % n,这对于小n来说并不完美。得到的随机数通常不均匀分布;较小的值会更频繁地返回。

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

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

答案 3 :(得分:3)

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

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

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

答案 4 :(得分:1)

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

试试这个:

#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);
}

答案 5 :(得分:1)

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

j = ((rand() >> 15) % 20;

答案 6 :(得分:1)

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;
}