web-dev-qa-db-fra.com

Comment fonctionne un générateur de nombres aléatoires?

Comment fonctionne le générateur de nombres aléatoires? (par exemple en C/C++ Java)

Comment puis-je écrire mon propre générateur de nombres aléatoires? (par exemple en C/C++ Java)

33
Rella

Il y a aussi cet algorithme: 

enter image description here

Oh, et plus sérieusement:

Les générateurs de nombres aléatoires utilisent des formules mathématiques qui transfèrent un ensemble de nombres à un autre. Si, par exemple, vous prenez un nombre constant N et un autre nombre n_0, puis prenez la valeur de n mod N (l'opérateur modulo), vous obtiendrez un nouveau nombre n_1, qui n'aura aucun rapport avec n_0. Maintenant, répétez le même processus avec n_1 et vous obtiendrez un autre numéro. Ce que vous avez ici est un générateur (TRES MAUVAIS) de nombres apparemment aléatoires. 

N'oubliez pas que la méthode que j'ai décrite ici est une méthode de jouet qui ne devrait pas être utilisée pour des problèmes graves. Il illustre toutefois le principe général.

Notez aussi:

Si tous les articles scientifiques dont les résultats sont douteux à cause de Rands disparaissaient des étagères de la bibliothèque, il y aurait un vide sur chaque étagère à peu près aussi grand que votre poing.

(Paraphrasé du chapitre 7 de Recettes numériques ). C'est un texte à lire absolument pour quiconque utilise des générateurs de nombres aléatoires pour des travaux sérieux.

21
Boris Gorelik

Auparavant, je les fabriquais en obtenant une valeur du système qui change très rapidement, par exemple la minuterie en millisecondes du système. 

La prochaine étape consiste à appliquer une formule qui générera un nouveau numéro à partir de ce numéro "d'entrée" et le découpera dans la plage souhaitée, par exemple 0..255:

nombre_aléatoire = nombre entier (formule (valeur du minuteur)) MOD 255

De cette façon, vous avez un nouveau numéro "aléatoire" chaque fois que vous appelez la fonction.

Un exemple de fonction de formule pourrait être:
formule (x) = ((x XOR constante) + constante2) gamme MOD
XOR était l’un de mes favoris.


Mise à jour: Je me rends compte que cette formule est très mauvaise, elle génère un ensemble assez prévisible de nombres. En outre, la minuterie du système est trop prévisible en tant que source. Donc, pour la plupart des applications, cela ne suffit pas. Si vous avez besoin d'un meilleur caractère aléatoire, utilisez davantage de sources que le minuteur système et meilleures formules pour les combiner.

5
thomaspaulb

J'ai trouvé celui-ci pour Java:

http://www.javamex.com/tutorials/random_numbers/Java_util_random_algorithm.shtml

en googlant comment fonctionnent les fonctions aléatoires Java

Je suis sûr que la réponse est spécifique à la langue, mais vous pouvez essayer de modifier ma requête Google pour la langue de votre choix.

3
David

Il y a beaucoup d'informations disponibles sur leur fonctionnement ... voyez la réponse de Konamiman et utilisez un peu Google.

Pourquoi voudriez-vous écrire un nouveau générateur aléatoire? Vous ne devriez probablement pas essayer de le faire ... jusqu'à ce que vous ayez besoin de quelque chose de très spécial. Par exemple, dans un jeu, vous pouvez utiliser un shuffle bag qui produit des valeurs aléatoires "correctes" - consultez cette question intéressante sur SO .
Je poste ceci ici, parce que j’ai vraiment aimé l’idée et la mise en oeuvre quand j’en ai lu un récit la première fois :)

1
tanascius

voici un code pour lancer les dés, il utilise un générateur de nombres aléatoires que j'ai développé moi-même le pad de ce RNG contient 15 valeurs hexadécimales au total 

 DIM pad(15) AS INTEGER
CLS
Egg$ = "EFCDBA01457FA968"
  ghh$ = Egg$
 nom% = 0
zen% = LEN(ghh$)
WHILE zen% > 0
opp$ = LEFT$(ghh$, 1)
eff% = ASC(opp$)
IF eff% >= 48 AND eff% <= 57 THEN eff% = eff% - 48 ELSE eff% = (eff% - 65) + 10
IF eff% > 15 THEN eff% = eff% - 32
pad(nom%) = eff%
nom% = nom% + 1
zen% = LEN(ghh$) - 1
ypp$ = RIGHT$(ghh$, zen%)
ghh$ = ypp$
WEND
sol& = 0
FOR zyx% = 0 TO 3
sol& = sol& * 16
sol& = sol& + pad(zyx%)
NEXT zyx%
sat% = sol& - 32768
RANDOMIZE sat%
FOR zyx% = 0 TO 15
PRINT HEX$(pad(zyx%));
NEXT zyx%
RANDOMIZE TIMER
respawn:
INPUT "sides per die"; die%
INPUT " number of dice"; dice%
INPUT "number to add to dice roll can be negative"; num%
INPUT "multiplier use 1 if so desired single precision floating point number"; g!
PRINT " hit any key to roll again with these values hit n for new values and q to quit"
PRINT " the number will be added or subtracted first before the multiplier takes effect"
reroll:
sum! = 0
FOR x% = 1 TO dice%
GOSUB rndmz
GOSUB demf
GOSUB drand
k% = INT(dr# * die%) + 1
sum! = sum! + k%
NEXT x%
sum! = (sum! + num) * g!
PRINT "you rolled a :"; sum!
i$ = ""
WHILE i$ = "": i$ = INKEY$: WEND
IF i$ = "n" THEN GOTO respawn
IF i$ = "q" THEN GOTO theend
GOTO reroll
theend:
SYSTEM
END
rndmz: rhet$ = ""
zum% = 0
FOR yxz% = 0 TO 15
FOR zyx% = 0 TO 15
IF zyx% MOD 3 = 0 THEN zum% = (zum% + pad(zyx%)) MOD 16
IF zyx% MOD 3 = 1 THEN zum% = (zum% + 16 - pad(zyx%)) MOD 16
IF zyx% MOD 3 = 2 THEN zum% = (zum% + INT(RND * 16)) MOD 16
NEXT zyx%
rhet$ = rhet$ + HEX$(zum%)
NEXT yxz%
ghh$ = rhet$
RETURN
demf: nom% = 0
zen% = LEN(ghh$)
WHILE zen% > 0
opp$ = LEFT$(ghh$, 1)
eff% = ASC(opp$)
IF eff% >= 48 AND eff% <= 57 THEN eff% = eff% - 48 ELSE eff% = (eff% - 65) + 10
IF eff% > 15 THEN eff% = eff% - 32
pad(nom%) = eff%
nom% = nom% + 1
zen% = LEN(ghh$) - 1
ypp$ = RIGHT$(ghh$, zen%)
ghh$ = ypp$
WEND
FOR zyx% = 0 TO 15
'PRINT HEX$(pad(zyx%));
NEXT zyx%
RETURN
drand: dr# = pad(0)
FOR eff% = 1 TO 15
dr# = dr# / 16
dr# = dr# + pad(eff%)
NEXT eff%
dr# = dr# / 16
RETURN
derf: a# = 1
x# = 1
b# = 1 / (2 ^ .5)
c# = .2500000000000011#
FOR u% = 1 TO 3
y# = a#
a# = (a# + b#) / 2
b# = (b# * y#) ^ .5
c# = c# - x# * (a# - y#) ^ 2
x# = 2 * x#
pi# = ((a# + b#) ^ 2) / (4 * c#)
PRINT pi#
NEXT u%
pi# = pi# + .000000000000015#
PRINT pi#

ceci ici à la fin calcule pi à presque autant de lieux possibles en seulement 3 boucles de l'algorithme, désolé qu'il soit écrit dans un langage de base archaïque, c'est le seul langage de programmation que je connaisse, il pourrait être possible de le porter en c ++ ou en Java
Il suffit d’examiner attentivement la logique de ce processus et de prêter une attention particulière aux procédures d’amorçage ou d’ensemencement/d’initialisation, qui doivent être utilisées sinon cela échouera comme bon jeu. J’en ai développé un pour le jeu où avoir une sécurité énorme n'est pas aussi une préoccupation que la vitesse ...

0
John Einem

Il est également courant de créer ces types de générateurs en utilisant quelque chose comme la cinquième décimale du temps d'horloge actuel qui nous semble également aléatoire. Additionnez les entrées de quelques systèmes chaotiques, par exemple données météorologiques, données boursières, encore une fois, en utilisant le module et vous avez un bon nombre de semences.

0
user3918295