在C中生成随机数

jq6vz3qz  于 12个月前  发布在  其他
关注(0)|答案(7)|浏览(127)

在C语言中搜索生成随机数的Tuesday时,我发现this topic
当我尝试使用不带参数的rand()函数时,我总是得到0。当我尝试使用带参数的rand()函数时,我总是得到值41。每当我尝试使用arc4random()random()函数时,我都会得到一个LNK 2019错误。
我是这么做的

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

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

vmpqdwk3

vmpqdwk31#

在调用兰德初始化随机数生成器之前,应该先调用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和兰德_MAX(stdlib. h中预定义的宏)之间具有相等概率的随机数

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

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)是一个流行的高质量随机数生成器。
另外,我不知道arc4rand()或random(),所以我不能评论。

vddsk6oq

vddsk6oq2#

您需要为PRNG设置种子,以便它每次都以不同的值开始。
一个简单但低质量的种子是使用当前时间:

srand(time(0));

这将让你开始,但被认为是低质量(即。例如,如果您试图生成RSA密钥,请不要使用它)。
伪随机数生成器并不创建真正的随机数序列,而只是模拟它们。给定一个起始点数字,PRNG将始终返回相同的数字序列。默认情况下,它们以相同的内部状态开始,因此将返回相同的序列。
为了不得到相同的序列,你改变了内部状态。改变内部状态的行为称为“播种”。

vc6uscn9

vc6uscn93#

#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年前,函数的定义不包括参数的数量或参数的类型。调用一个未知的函数也是可以的,在大多数情况下都可以工作。如果你现在想写代码,你不应该依赖这些旧的功能,而是启用编译器的警告,理解警告,然后正确地修复它们。

d4so4syb

d4so4syb4#

此外,线性全等PRNG倾向于在高位上产生比低位上更大的随机性,因此不要使用模来限制结果,而是使用类似于:

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

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

jm2pwxwz

jm2pwxwz5#

你首先需要 seed 生成器,因为它不会生成 * 真实的 * 随机数!
试试这个:

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

fwzugrvs6#

或者,要获得范围为0到19的伪随机整数,例如,您可以像这样使用高位:

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

nnt7mjpx7#

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

相关问题