Comment fonctionne rand ()? A-t-il certaines tendances? Y a-t-il quelque chose de mieux à utiliser?
J'ai lu que cela a quelque chose à voir avec le temps, aussi, vous obtenez à partir de, incluant le temps.h, donc, je suppose que beaucoup, mais comment ça marche exactement? Aussi, a-t-elle toute tendance vers les nombres pairs ou impairs ou quelque chose comme ça? Et enfin il y a une chose avec une meilleure répartition dans la bibliothèque C standard ou de la Fondation du cadre?
source d'informationauteur Regan
Vous devez vous connecter pour publier un commentaire.
Brièvement:
Vous utilisez
time.h
obtenir une graine, qui est un premier nombre aléatoire. C fait ensuite un tas d'opérations sur ce nombre pour obtenir le numéro aléatoire suivant, puis des opérations sur celui-ci pour obtenir la prochaine, alors... vous obtenez l'image.rand()
est capable de toucher à tous les possibles entier. Il préfère pas les numéros pairs ou impairs, indépendamment de l'entrée de la graine, heureusement. Encore, il a ses limites - il se répète assez rapidement, et pratiquement à chaque mise en œuvre ne donne que des nombres jusqu'à 32767.C n'ont pas d'autre built-in générateur de nombre aléatoire. Si vous avez besoin d'un vrai dur de dur, il y a beaucoup de paquets disponibles en ligne, mais la Mersenne Twister algorithme est probablement le plus populaire de sélection.
Maintenant, si vous êtes intéressé sur les raisons pourquoi ci-dessus est vrai, voici les détails sanglants sur la façon
rand()
travaux:rand()
est ce qu'on appelle un "générateur linéaire à congruence." Cela signifie qu'il utilise une équation de la forme:xn+1 = (*****xn + ***b****) mod m
où xn est le nème de nombre aléatoire, et un et b sont certains prédéterminé entiers. Le calcul est effectué modulo mavec m généralement de 232 en fonction de la machine, de sorte que seul le plus faible de 32 bits sont conservés dans le calcul de xn+1.
En anglais, alors, l'idée est la suivante: Pour obtenir le numéro aléatoire suivant, multipliez le dernier nombre aléatoire par quelque chose, pour ajouter un numéro, puis prendre le dernier quelques chiffres.
Quelques limitations sont rapidement visibles:
Tout d'abord, vous avez besoin d'un départ de nombre aléatoire. C'est la "semence" de votre générateur de nombre aléatoire, et c'est là que vous avez entendu parler de
time.h
utilisé. Puisque nous voulons vraiment un nombre aléatoire, il est de pratique courante de demander au système de l'heure qu'il est (en entier) et l'utiliser comme la première "nombre aléatoire." Aussi, c'est ce qui explique pourquoi l'utilisation de la même semence deux fois toujours donner exactement la même séquence de nombres aléatoires. Cela semble mauvais, mais qui est en fait utile, car le débogage est beaucoup plus facile lorsque vous contrôlez les entrées de votre programmeDeuxième, un et b doivent être choisis très, très bien ou vous obtiendrez des résultats désastreux. Heureusement, l'équation pour un générateur linéaire à congruence est assez simple pour que les mathématiques a été travaillé dans le détail. Il s'avère que le choix d'une un qui satisfait ****mod8 = 5 avec le ***b* * * * = 1 s'assurer que tous les m entiers sont tout aussi probable, indépendant du choix de la graine. Vous aussi vous voulez une valeur de un qui est vraiment très grand, de sorte que chaque fois que vous le multipliez par xnvous pouvez déclencher le modulo et couper la beaucoup de chiffres, ou bien beaucoup de nombres dans une ligne juste être accolés les uns des autres. En conséquence, les deux valeurs communes de la un (par exemple) sont 1566083941 et 1812433253 selon Knuth. La bibliothèque C de GNU arrive à utiliser un=1103515245 et b=12345. Une liste de valeurs pour les lots de mises en œuvre est disponible à la page wikipedia pour LCGs.
Troisième, le générateur linéaire à congruence va effectivement se répéter à cause de cela modulo. Cela devient un peu assez grisant de mathématiques, mais le résultat de tout cela est heureusement très simple: La séquence se répète après m nombre de ont été générés. Dans la plupart des cas, cela signifie que votre générateur de nombre aléatoires répéter tous les 232 cycles. Cela ressemble à beaucoup, mais il n'est vraiment pas pour de nombreuses applications. Si vous êtes à la réalisation des résultats numériques avec des simulations de Monte Carlo, ce nombre est complètement inadéquat.
Un quatrième beaucoup moins de problème évident est que les chiffres ne sont pas réellement vraiment aléatoire. Ils ont un drôle de sorte de corrélation. Si vous prenez trois nombres entiers consécutifs, (xyz), à partir d'une GRILLE avec une certaine valeur de un et mces trois points toujours tomber sur le treillis de points générés par l'ensemble des combinaisons linéaires des trois points (1, a, a2), (0, m, 0), (0, 0, m). Ceci est connu comme Marsaglia du Théorème, et si vous ne le comprenez pas, c'est normal. Tout cela signifie, c'est ceci: les Triplets de nombres aléatoires à partir d'une GRILLE permettra de montrer les corrélations à une certaine profondeur, le niveau de profondeur. Habituellement, il est trop profonde pour vous et moi d'avis, mais il est là. Il est possible même de reconstruire le premier nombre "aléatoire" de la séquence de trois chiffres si vous êtes donné le deuxième et le troisième! Ce n'est pas bon pour la cryptographie à tous.
La bonne nouvelle est que LCGs comme
rand()
sont très, très faible encombrement. En général, il requiert seulement 32 bits pour conserver l'état, ce qui est vraiment agréable. Il est également très rapide, ne nécessitant que très peu d'opérations. Comme cela, il est bon pour les non critique des systèmes embarqués, des jeux vidéo, décontracté, des applications, des trucs comme ça.PRNGs sont un sujet fascinant. Wikipedia est toujours un bon endroit où aller si vous êtes à la soif d'en apprendre plus sur l'histoire ou les diverses implémentations qui sont autour d'aujourd'hui.
rand
renvoie des nombres générés par un générateur de nombres pseudo aléatoires (PRNG). La séquence de chiffres qu'elle renvoie est déterministe, basée sur la valeur avec laquelle le GÉNÉRATEUR a été initialisé (en appelantsrand
).Les chiffres devraient être répartis de telle sorte qu'ils apparaissent quelque peu aléatoire, de sorte que, par exemple, pair et impair de nombres doivent être retournés à peu près la même fréquence. La mise en œuvre réelle du générateur de nombre aléatoire n'est spécifié, alors le comportement est spécifique à la mise en œuvre.
La chose importante à retenir est que
rand
ne retourne pas de nombres aléatoires; il renvoie des nombres pseudo-aléatoires, et les valeurs qu'il renvoie sont déterminés par la valeur de départ et le nombre de foisrand
a été appelé. Ce comportement est très bien pour de nombreux cas d'utilisation, mais n'est pas approprié pour d'autres (par exemple,rand
ne serait pas approprié pour une utilisation dans de nombreuses applications cryptographiques).http://en.wikipedia.org/wiki/Pseudorandom_number_generator
rand()
n'a rien à voir avec le temps. Cependant, il est très courant d'utilisertime()
pour obtenir la "semence" pour le GÉNÉRATEUR de sorte que vous obtenez différents "aléatoire" des chiffres chaque fois que votre programme est exécuté.Dépend de la précision de la méthode utilisée. Il y a une populaire de la mise en œuvre de
rand()
que suppléants entre pair et impair de chiffres. Donc, éviter d'écrire du code commerand() % 2
qui dépend du bit de poids faible étant aléatoire.