Ce document présente la méthode d'utilisation des fonctions pour générer des nombres aléatoires en C/C++ rand
et fournit divers exemples de codes couramment utilisés.
Lors de l'écriture de programmes C/C++, si vous avez besoin de générer des nombres aléatoires simples, le moyen le plus pratique consiste à utiliser rand
cette fonction de générateur de nombres aléatoires. Ce qui suit présente l'utilisation associée et des exemples de cette fonction.
rand
Il ne peut fournir que des nombres aléatoires de base. Si vous avez besoin de fonctions plus avancées ou de nombres aléatoires de meilleure qualité, il est recommandé d'utiliser<random>
à la place la bibliothèque de fonctions C++.
Méthode de base de génération de nombres aléatoires
Pour générer des nombres aléatoires en langage C, vous pouvez utiliser la fonction stdlib.h
dans rand
, et rand
avant d'appeler la fonction, vous devez d'abord utiliser srand
la fonction pour définir la graine initiale du nombre aléatoire :
#include <stdio.h> |
|
#include <stdlib.h> /*乱数相关函数*/ |
|
#include <time.h> /*时间相关函数*/ |
|
int main(){
|
|
/*设定随机数种子*/ |
|
srand( time( NULL ) ); |
|
/*生成随机数*/ |
|
int x = rand(); |
|
printf( "x = %d \n " , x); |
|
return 0 ; |
|
} |
La sortie après exécution est :
<span style="background-color:#f8f8f8"><span style="color:#212529">x = 159136674</span></span>
rand
Le nombre aléatoire généré est un entier dont la valeur est comprise 0
entre RAND_MAX
et (le plus petit est 0
, le plus grand est RAND_MAX
), si vous voulez voir RAND_MAX
la valeur réelle, vous pouvez printf
l'utiliser pour la sortir et la vérifier.
<span style="background-color:#f8f8f8"><span style="color:#212529"><code class="language-cpp"><span style="color:#f69d50">printf</span>( <span style="color:#96d0ff">"RAND_MAX = %d \n "</span> , RAND_MAX );</code></span></span>
La méthode de génération de nombres aléatoires en C++ est presque la même qu'en C, seul le fichier d'en-tête est modifié :
#include <iostream> |
|
#include <cstdlib> /*随机数相关函数*/ |
|
#include <ctime> /*时间相关函数*/ |
|
int main(){
|
|
/*固定随机数种子*/ |
|
srand( time( NULL ) ); |
|
/*生成随机数*/ |
|
int x = rand(); |
|
std::cout << "x = " << x << std::endl; |
|
return 0 ; |
|
} |
Pour les exemples suivants, j'utiliserai le langage C comme standard, et ceux qui ont besoin de C++ peuvent modifier eux-mêmes le fichier d'en-tête.
graine de nombre aléatoire fixe
Étant donné que l'ordinateur n'a en fait aucun moyen de générer de "vrais nombres aléatoires" par lui-même, il ne peut simuler des données numériques similaires à des nombres aléatoires qu'à l'aide d'algorithmes mathématiques complexes. Lors de la simulation de nombres aléatoires, il est nécessaire de définir une graine de nombre aléatoire, l'ordinateur A une série de nombres aléatoires sera calculée sur la base de cette graine de nombre aléatoire, et la même graine de nombre aléatoire générera la même séquence de nombres aléatoires, donc si vous voulez que les nombres aléatoires générés soient différents à chaque fois, vous devez définir une graine de nombre aléatoire différente .
Dans l'exemple ci-dessus, nous utilisons le temps comme graine de nombre aléatoire, de sorte que les nombres aléatoires générés à chaque fois sont différents. S'il s'agit d'un programme de simulation numérique, il est généralement nécessaire de rendre les résultats de simulation reproductibles. C'est pratique pour le débogage et Dans ce cas, la graine du nombre aléatoire peut être fixée, de manière à garantir que les résultats de la simulation sont exactement les mêmes à chaque fois :
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <time.h> |
|
int main(){
|
|
/*固定乱数种子*/ |
|
srand( 5 ); |
|
int x = rand(); |
|
printf( "x = %d \n " , x); |
|
return 0 ; |
|
} |
<span style="background-color:#f8f8f8"><span style="color:#212529">x = 84035</span></span>
La graine du nombre aléatoire est définie avec un entier. Si vous souhaitez fixer la graine du nombre aléatoire, peu importe la valeur à définir, tant que la même graine du nombre aléatoire est utilisée à chaque exécution du programme.
Le moment le plus courant pour utiliser une graine de nombre aléatoire fixe peut être lors du débogage ou de la vérification d'une erreur dans l'algorithme. S'il n'y a pas de graine de nombre aléatoire fixe, les résultats seront différents à chaque exécution, ce qui rendra le débogage Plus difficile.
[0, 1)
nombre aléatoire à virgule flottante
Pour générer des nombres aléatoires 0
entre 1
des nombres à virgule flottante, vous pouvez écrire :
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <time.h> |
|
int main(){
|
|
srand( time( NULL ) ); |
|
/*产生[ 0 , 1 ) 的浮点数随机数*/ |
|
double x = ( double ) rand() / ( RAND_MAX + 1.0 ); |
|
printf( "x = %f \n " , x); |
|
return 0 ; |
|
} |
Dans le code ci-dessus, nous rand
divisons l'entier généré par la fonction par RAND_MAX + 1.0
, et nous pouvons obtenir [0, 1)
le nombre aléatoire de nombres à virgule flottante dans cette plage (c'est-à-dire 0 <= x < 1
).
Plage spécifique nombre aléatoire à virgule flottante
Pour générer des nombres aléatoires à virgule flottante dans une plage spécifique, vous pouvez écrire :
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <time.h> |
|
int main(){
|
|
srand( time( NULL ) ); |
|
/*指定随机数范围*/ |
|
double min = 3.6 ; |
|
double max = 7.8 ; |
|
/*产生[min , max) 的浮点数随机数*/ |
|
double x = (max - min) * rand() / ( RAND_MAX + 1.0 ) + min; |
|
printf( "x = %f \n " , x); |
|
return 0 ; |
|
} |
[min , max)
De cette manière, des nombres aléatoires entre des nombres à virgule flottante peuvent être générés .
Nombre entier aléatoire dans une plage spécifique
Si vous souhaitez générer un nombre aléatoire d'entiers dans une plage spécifique, vous pouvez écrire :
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <time.h> |
|
int main(){
|
|
srand( time( NULL ) ); |
|
/*指定随机数范围*/ |
|
int min = 4 ; |
|
int max = 10 ; |
|
/*产生[min , max] 的整数随机数*/ |
|
int x = rand() % (max - min + 1 ) + min; |
|
printf( "x = %d \n " , x); |
|
return 0 ; |
|
} |
Cela rand
convertit l'entier résultant en [min , max]
un nombre entier aléatoire (c'est-à-dire min <= x <= max
).
La méthode ci-dessus d'utilisation de l'opération de reste ( %
) est juste une manière plus pratique d'écrire. En fait, les nombres aléatoires entiers générés en utilisant l'opération de reste ne sont pas une distribution uniforme standard en théorie. Expliquons-le avec un exemple simple. valeur RAND_MAX
est 10
, Et nous voulons générer un nombre entier aléatoire entre 3
et 5
(c'est-à-dire min = 3
, max = 5
), voici un tableau de comparaison de toutes les possibilités :
nombre entier aléatoire converti | rand nombre aléatoire généré par la fonction |
Probabilité d'occurrence |
---|---|---|
3 |
0 、3 、6 、9 |
4/11 |
4 |
1 、4 、7 、10 |
4/11 |
5 |
2 、5 、8 |
3/11 |
rand
函数所产生的每一个整数其出现的机率是均等的,但是经过于数运算的转换之后,因为 RAND_MAX
通常不会被整除,所以转换之后的整数随机数出现机率就存在有细微的偏差,以这个例子来说,3
、4
、5
三个数字出现的机率比是4:4:3
。
另外有些人会先产生固定范围的浮点数随机数,再将浮点数转型为整数,例如产生 [3, 6)
的浮点数随机数,然后转型为 [3, 5]
的整数随机数,其实这种方式跟余数运算一样会有每个整数出现机率不均等的问题,简单来说就是现在有 11
个球要放进 3
个篮子里,不管怎么放,每个篮子的球都不可能一样多。
如果您需要非常标准的均匀分布(uniform distribution),可以使用这个版本:
/*产生[ 0 , n) 均匀分布的整数随机数*/ |
|
int randint( int n) {
|
|
if ((n - 1 ) == RAND_MAX ) {
|
|
return rand(); |
|
} else {
|
|
/*计算可以被整除的长度*/ |
|
long end = RAND_MAX / n; |
|
assert (end > 0L ); |
|
end *= n; |
|
/*将尾端会造成偏差的几个随机数去除, |
|
若产生的乱数超过limit,则将其舍去*/ |
|
int r; |
|
while ((r = rand()) >= end); |
|
return r % n; |
|
} |
|
} |
使用这个 randint
函数产生特定范围整数随机数:
/*指定随机数范围*/ |
|
int min = 4 ; |
|
int max = 10 ; |
|
/*产生[min , max] 的整数随机数*/ |
|
int x = randint(max - min + 1 ) + min; |
这种作法就好像要把 11
个球要放进 3
个篮子里,而最后多出来的 2
颗球就直接丢掉,确保每个篮子都一样只有 3
颗,这样大家的机率就可以相等了。
这种使用截断分布(truncated distribution)来校正机率的方式虽然在理论上是正确的,但是 rand
函数是使用LCG(Linear Congruential Generator)来产生随机数的,他的优点只是快速、方便而已,但它本身所产生的随机数品质没有非常好,再怎么校正效果都有限,若需要高品质的随机数,请改用C++11 标准的 <random>
函数库。