28 votes

Pourquoi les chiffres 1, 2 et 3 apparaissent-ils si fréquemment en utilisant la fonction C rand ()?

Ce que j'essaie de faire est de générer des nombres aléatoires (pas nécessairement à un seul chiffre) comme

29106
7438
5646
4487
9374
28671
92
13941
25226
10076

et puis de compter le nombre de chiffres que j'obtiens:

count[0] =       3  Percentage =  6.82
count[1] =       5  Percentage = 11.36
count[2] =       6  Percentage = 13.64
count[3] =       3  Percentage =  6.82
count[4] =       6  Percentage = 13.64
count[5] =       2  Percentage =  4.55
count[6] =       7  Percentage = 15.91
count[7] =       5  Percentage = 11.36
count[8] =       3  Percentage =  6.82
count[9] =       4  Percentage =  9.09

C'est le code, je suis en utilisant:

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

int main() {

    int i;
    srand(time(NULL));
    FILE* fp = fopen("random.txt", "w");    
    // for(i = 0; i < 10; i++)
    for(i = 0; i < 1000000; i++)
        fprintf(fp, "%d\n", rand());
    fclose(fp);

    int dummy;
    long count[10] = {0,0,0,0,0,0,0,0,0,0};
    fp = fopen("random.txt", "r");
    while(!feof(fp)) {
        fscanf(fp, "%1d", &dummy);
        count[dummy]++;                 
    }
    fclose(fp);

    long sum = 0;
    for(i = 0; i < 10; i++)
        sum += count[i];

    for(i = 0; i < 10; i++)
        printf("count[%d] = %7ld  Percentage = %5.2f\n",
            i, count[i], ((float)(100 * count[i])/sum));

}

Si je générer un grand nombre de nombres aléatoires (1000000), c'est le résultat que j'obtiens:

count[0] =  387432  Percentage =  8.31
count[1] =  728339  Percentage = 15.63
count[2] =  720880  Percentage = 15.47
count[3] =  475982  Percentage = 10.21
count[4] =  392678  Percentage =  8.43
count[5] =  392683  Percentage =  8.43
count[6] =  392456  Percentage =  8.42
count[7] =  391599  Percentage =  8.40
count[8] =  388795  Percentage =  8.34
count[9] =  389501  Percentage =  8.36

Notez que 1, 2 et 3 ont trop de succès. J'ai essayé de lancer cette opération plusieurs fois et à chaque fois j'obtiens des résultats très similaires.

Je suis en train d'essayer de comprendre quelle est la cause de 1, 2 et 3 apparaissent beaucoup plus fréquemment que n'importe quel autre chiffre.


La prise de soupçon de ce que Matt Menuisier et Pascal Cuoq a souligné,

J'ai changé le code à utiliser

for(i = 0; i < 1000000; i++)
    fprintf(fp, "%04d\n", rand() % 10000);
// pretty prints 0
// generates numbers in range 0000 to 9999

et c'est ce que j'obtiens (des résultats similaires sur plusieurs pistes):

count[0] =  422947  Percentage = 10.57
count[1] =  423222  Percentage = 10.58
count[2] =  414699  Percentage = 10.37
count[3] =  391604  Percentage =  9.79
count[4] =  392640  Percentage =  9.82
count[5] =  392928  Percentage =  9.82
count[6] =  392737  Percentage =  9.82
count[7] =  392634  Percentage =  9.82
count[8] =  388238  Percentage =  9.71
count[9] =  388352  Percentage =  9.71

Quelle peut être la raison de 0, 1 et 2 sont favorisés?


Merci à tous. À l'aide de

int rand2(){
    int num = rand();
    return (num > 30000? rand2():num);     
}

    fprintf(fp, "%04d\n", rand2() % 10000);

Je reçois

count[0] =  399629  Percentage =  9.99
count[1] =  399897  Percentage = 10.00
count[2] =  400162  Percentage = 10.00
count[3] =  400412  Percentage = 10.01
count[4] =  399863  Percentage = 10.00
count[5] =  400756  Percentage = 10.02
count[6] =  399980  Percentage = 10.00
count[7] =  400055  Percentage = 10.00
count[8] =  399143  Percentage =  9.98
count[9] =  400104  Percentage = 10.00

46voto

Matt Joiner Points 29194

rand() génère une valeur à partir d' 0 de RAND_MAX. RAND_MAX est définie à l' INT_MAX sur la plupart des plates-formes, qui peuvent être 32767 ou 2147483647.

Pour votre exemple donné ci-dessus, il semble que l' RAND_MAX est 32767. Cela aura lieu exceptionnellement à haute fréquence d' 1, 2 et 3 pour les chiffres plus importantes pour les valeurs de 10000 de 32767. Vous pouvez observer que, dans une moindre mesure, les valeurs de 6 et 7 sera également légèrement favorisés.

20voto

KennyTM Points 232647

Concernant la modification de la question,

C'est parce que les chiffres ne sont toujours pas distribués de manière uniforme, même si vous % 10000. Supposons RAND_MAX == 32767, et rand() est parfaitement uniforme.

Pour chaque tranche de 10 000 numéros à compter à partir de 0, tous les chiffres apparaissent de manière uniforme (de 4 000 chacun). Cependant, de 32 767 n'est pas divisible par 10 000. Par conséquent, ces 2,768 les numéros de fournir plus de 0, 1 et 2 pour le décompte final.

La contribution exacte de ces 2,768 numéros sont les suivants:

digits count
0      1857
1      1857
2      1625
3      857
4      857
5      857
6      855
7      815
8      746
9      746

l'ajout de 12 000 pour la période initiale de 30 000 numéros le comte, puis diviser par le nombre total de chiffres (4×32,768) devrait vous donner la distribution attendue:

number  probability (%)
0       10.5721
1       10.5721
2       10.3951
3        9.80911
4        9.80911
5        9.80911
6        9.80759
7        9.77707
8        9.72443
9        9.72443

ce qui est proche de ce que vous obtenez.

Si vous voulez vraiment uniforme chiffres de la distribution, vous devez rejeter ceux 2,768 numéros:

int rand_4digits() {
  const int RAND_MAX_4_DIGITS = RAND_MAX - RAND_MAX % 10000;
  int res;
  do {
    res = rand();
  } while (res >= RAND_MAX_4_DIGITS);
  return res % 10000;
}

2voto

phimuemue Points 11644

C'est parce que vous générez des nombres entre 0 et RAND_MAX . Les nombres générés sont répartis uniformément (c.-à-d. Approximativement la même probabilité pour chaque nombre), cependant, les chiffres 1, 2, 3 se produisent plus souvent que les autres dans cette plage. Essayez de générer entre 0 et 10 , où chaque chiffre se produit avec la même probabilité et vous obtiendrez une bonne distribution.

2voto

samiam Points 379

Si je comprends ce que l'OP (la personne qui pose la question) veut, ils veulent faire de mieux nombres aléatoires.

rand() et random(), franchement, ne font pas de très bon nombres aléatoires; ils ont tous deux faire mal lors d'un essai contre irréductibles et dieharder (deux paquets pour tester la qualité de nombres aléatoires).

Le Mersenne twister populaire est un générateur de nombre aléatoire qui est bon pour à peu près tout, sauf de la crypto-fort nombres aléatoires; il passe tous les inconditionnels de(re) avec brio.

Si l'on a besoin de crypto-fort aléatoire de nombres (les nombres qui ne peuvent pas être deviné, même si quelqu'un sait de quelle crypto-fort algorithme est utilisé), il y a un certain nombre de chiffrements de flux là-bas. Celui que j'aime utiliser est appelé RadioGatún[32], et voici un compact C de la représentation de celui-ci:

/*Placed in the public domain by Sam Trenholme*/
#include <stdint.h>
#include <stdio.h> 
#define p uint32_t
#define f(a) for(c=0;c<a;c++)
#define n f(3){b[c*13]^=s[c];a[16+c]^=s[c];}k(a,b 
k(p *a,p *b){p A[19],x,y,r,q[3],c,i;f(3){q[c]=b[c
*13+12];}for(i=12;i;i--){f(3){b[c*13+i]=b[c*13+i- 
1];}}f(3){b[c*13]=q[c];}f(12){i=c+1+((c%3)*13);b[
i]^=a[c+1];}f(19){y=(c*7)%19;r=((c*c+c)/2)%32;x=a
[y]^(a[(y+1)%19]|(~a[(y+2)%19]));A[c]=(x>>r)|(x<<
(32-r));}f(19){a[c]=A[c]^A[(c+1)%19]^A[(c+4)%19];
}a[0]^=1;f(3){a[c+13]^=q[c];}}l(p *a,p *b,char *v
){p s[3],q,c,r,x,d=0;for(;;){f(3){s[c]=0;}for(r=0
;r<3;r++){for(q=0;q<4;q++){if(!(x=*v&255)){d=x=1;
}v++;s[r]|=x<<(q*8);if(d){n);return;}}}n);}}main(
int j,char **h){p a[39],b[39],c,e,g;if(j==2){f(39
){a[c]=b[c]=0;}l(a,b,h[1]);f(16){k(a,b);}f(4){k(a
,b);for(j=1;j<3;++j){g=a[j];for(e=4;e;e--){printf
("%02x",g&255);g>>=8;}}}printf("\n");}}

Il y a aussi beaucoup d'autres vraiment bon générateurs de nombres aléatoires là-bas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X