简体   繁体   English

在C中生成随机数

[英]Generating random numbers in C

While searching for Tutorials on generating random numbers in CI found this topic 在搜索有关在CI中生成随机数的教程时,发现了该主题

When I try to use the rand() function without parameters, I always get 0. When I try to use the rand() function with parameters, I always get the value 41. And whenever I try to use arc4random() and random() functions, I get a LNK2019 error. 当我尝试使用不带参数的rand()函数时,我总是得到0。当我尝试对参数使用rand()函数时,我总是得到值41。并且每当我尝试使用arc4random()random()函数,出现LNK2019错误。

Here's what I've done: 这是我所做的:

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

This code always generates 41. Where am I going wrong? 这段代码总是生成41。我在哪里出错? I'm running Windows XP SP3 and using VS2010 Command Prompt as compiler. 我正在运行Windows XP SP3,并使用VS2010命令提示符作为编译器。

You should call srand() before calling rand to initialize the random number generator. 在调用rand初始化随机数生成器之前,应先调用srand()。

Either call it with a specific seed, and you will always get the same pseudo-random sequence 用特定的种子调用它,您将始终获得相同的伪随机序列

#include <stdlib.h>

int main ()
{
  srand ( 123 );
  int random_number = rand();
  return 0;
}

or call it with a changing sources, ie the time function 或用变化的源调用它,即时间函数

#include <stdlib.h>
#include <time.h>

int main ()
{
  srand ( time(NULL) );
  int random_number = rand();
  return 0;
}

In response to Moon's Comment rand() generates a random number with an equal probability between 0 and RAND_MAX (a macro pre-defined in stdlib.h) 响应Moon的注释, rand()生成一个随机数,其概率在0到RAND_MAX之间(在stdlib.h中预定义了一个宏)

You can then map this value to a smaller range, eg 然后,您可以将此值映射到较小的范围,例如

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)

This might be sufficient for most uses, but its worth pointing out that in the first case using the mod operator introduces a slight bias if N does not divide evenly into RAND_MAX+1. 对于大多数用途而言,这可能就足够了,但值得指出的是,在第一种情况下,如果N不能平均划分为RAND_MAX + 1,则使用mod运算符会引起轻微的偏差。

Random number generators are interesting and complex, it is widely said that the rand() generator in the C standard library is not a great quality random number generator, read ( http://en.wikipedia.org/wiki/Random_number_generation for a definition of quality). 随机数生成器有趣且复杂,众所周知,C标准库中的rand()生成器不是高质量的随机数生成器,有关详细信息,请阅读( http://en.wikipedia.org/wiki/Random_number_generation质量)。

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

Also, I am not aware of arc4rand() or random() so I cannot comment. 另外,我不知道arc4rand()或random(),所以无法发表评论。

You need to seed your PRNG so it starts with a different value each time. 您需要播种PRNG,以便每次以不同的值开头。

A simple but low quality seed is to use the current time: 一个简单但质量低下的种子是使用当前时间:

srand(time(0));

This will get you started but is considered low quality (ie for example, don't use that if you are trying to generate RSA keys). 这会让您入门,但是被认为是低质量的 (例如,如果您尝试生成RSA密钥,请不要使用它)。

Background. 背景。 Pseudo-random number generators do not create true random number sequences but just simulate them. 伪随机数生成器不会创建真正的随机数序列,而只是模拟它们。 Given a starting point number, a PRNG will always return the same sequence of numbers. 给定起点编号,PRNG将始终返回相同的编号序列。 By default, they start with the same internal state so will return the same sequence. 默认情况下,它们以相同的内部状态开始,因此将返回相同的序列。

To not get the same sequence, you change the internal state. 要获得不同的序列,请更改内部状态。 The act of changing the internal state is called "seeding". 改变内部状态的行为称为“种子”。

#include <stdlib.h>

int main()
{
    int x;
    x = rand(6);
    printf("%d", x);
}

Especially as a beginner, you should ask your compiler to print every warning about bad code that it can generate. 特别是对于初学者,您应该要求编译器输出有关可能生成的错误代码的所有警告。 Modern compilers know lots of different warnings which help you to program better. 现代编译器知道许多不同的警告,可以帮助您更好地进行编程。 For example, when you compile this program with the GNU C Compiler: 例如,当您使用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'

You get two warnings here. 您在此处收到两个警告。 The first one says that the rand function only takes zero arguments, not one as you tried. 第一个说rand函数只接受零个参数,而不是您尝试的一个。 To get a random number between 0 and n , you can use the expression rand() % n , which is not perfect but ok for small n . 要获得介于0和n之间的随机数,可以使用表达式rand() % n ,这不是完美的,但对于小n The resulting random numbers are normally not evenly distributed; 产生的随机数通常不均匀分布; smaller values are returned more often. 较小的值返回的频率更高。

The second warning tells you that you are calling a function that the compiler doesn't know at that point. 第二个警告告诉您正在调用编译器当时不知道的函数。 You have to tell the compiler by saying #include <stdio.h> . 您必须通过说#include <stdio.h>来告诉编译器。 Which include files are needed for which functions is not always simple, but asking the Open Group specification for portable operating systems works in many cases: http://www.google.com/search?q=opengroup+rand . 需要哪些包含文件,对于这些文件来说,功能并不总是那么简单,但是在许多情况下要求便携式操作系统的Open Group规范起作用: http : //www.google.com/search?q=opengroup+rand

These two warnings tell you much about the history of the C programming language. 这两个警告告诉您有关C编程语言的历史的更多信息。 40 years back, the definition of a function didn't include the number of parameters or the types of the parameters. 40年前,函数的定义不包括参数的数量或参数的类型。 It was also ok to call an unknown function, which in most cases worked. 也可以调用未知函数,该函数在大多数情况下都有效。 If you want to write code today, you should not rely on these old features but instead enable your compiler's warnings, understand the warnings and then fix them properly. 如果您想今天编写代码,则不应依赖这些旧功能,而应启用编译器的警告,了解警告,然后正确进行修复。

Also, linear congruential PRNGs tend to produce more randomness on the higher bits that on the lower bits, so to cap the result don't use modulo, but instead use something like: 同样,线性同余PRNG倾向于在较高位上产生较高的随机性,而在较低位上产生更大的随机性,因此要限制结果,请不要使用模数,而应使用类似以下内容:

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

(This one is from "Numerical Recipes in C", ch.7) (这是来自“ C的数字食谱”,第7章)

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

You first need to seed the generator because it doesn't generate real random numbers! 首先,您需要为生成器添加种子 ,因为它不会生成真正的随机数!

Try this: 尝试这个:

#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范围内的伪随机整数,可以使用如下更高的位:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM