C语言 在 C 中生成随机数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3067364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:41:35  来源:igfitidea点击:

Generating random numbers in C

crandom

提问by MoonStruckHorrors

While searching for Tutorials on generating random numbers in C I 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? I'm running Windows XP SP3 and using VS2010 Command Prompt as compiler.

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

回答by Akusete

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 Commentrand() 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, e.g.

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

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_generationfor 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() 所以我不能评论。

回答by R Samuel Klatchko

You need to seed your PRNG so it starts with a different value each time.

您需要为 PRNG 设置种子,以便它每次都以不同的值开始。

A simple but low qualityseed is to use the current time:

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

srand(time(0));

This will get you started but is considered low quality(i.e. 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. By default, they start with the same internal state so will return the same sequence.

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

To not get the same sequence, you change the internal state. The act of changing the internal state is called "seeding".

为了不获得相同的序列,您可以更改内部状态。改变内部状态的行为称为“播种”。

回答by Roland Illig

#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 randfunction only takes zero arguments, not one as you tried. 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. The resulting random numbers are normally not evenly distributed; smaller values are returned more often.

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

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>. 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.

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

These two warnings tell you much about the history of the C programming language. 40 years back, the definition of a function didn't include the number of parameters or the types of the parameters. 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.

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

回答by ninjalj

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章)

回答by andy

Or, to get a pseudo-random int in the range 0 to 19, for example, you could use the higher bits like this:

或者,例如,要获得 0 到 19 范围内的伪随机整数,您可以使用更高的位,如下所示:

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

回答by Naveen Tulseela

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

回答by AraK

You first need to seedthe generator because it doesn't generate realrandom 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);
}