12
votes

Essayer de comprendre la fonction `aléatoire` dans HASKELLL

Je viens de tirer sur fonction aléatoire .

à ma compréhension, Fonction aléatoire prend une valeur de type qui est une instance de randomgen et renvoie une valeur aléatoire dont nous pouvons spécifier la valeur. D'autre part, mksdgen prend un int et génère un générateur aléatoire que aléatoire fonction de fonction "

J'essayais Pour générer des valeurs aléatoires bool . Pour ce faire, j'ai fait une fonction randombool . xxx

puis j'ai trouvé beaucoup plus vrai S false s avec petit nombre. Et j'étais curieux de cela et j'ai vérifié comme suit xxx

Je pense que cela signifie que pour les premiers entiers positifs 53667, aléatoire. mkstdgen retourne true , qui ne semble pas être très aléatoire pour moi. Est-ce très normal? Ou est-ce que je fais quelque chose de mal qui fait vrai se produise plus facilement?


0 commentaires

3 Réponses :


2
votes

Un générateur aléatoire créé par mkstdgen ne génère pas nécessairement une valeur aléatoire comme premier résultat. Pour générer le numéro aléatoire suivant, utilisez le générateur aléatoire renvoyé par l'appel aléatoire aléatoire précédent.

Par exemple, ce code génère 10 bool s. < Pré> xxx


1 commentaires

Pour élaborer sur ceci: le générateur aléatoire n'est pas garanti d'avoir une distribution aléatoire sur les valeurs de la graine, mais il est garanti de donner une distribution aléatoire sur des séquences de valeurs produites.



16
votes

de manière informelle, lorsque vous appelez mkstdgen code> avec des graines rapprochées, vous obtiendrez deux générateurs "similaires". Dans votre exemple, vous créez réellement de nouveaux générateurs pour chaque graine fournie et que ces graines sont 1, 2, 3, etc., elles produiront des flux similaires.

Lorsque vous appelez aléatoire code> Avec un générateur, vous récupérez réellement un nouveau générateur dans le deuxième élément de la paire: p> xxx pré>

donc une bonne idée est d'utiliser ce générateur fourni pour votre prochain appel à aléatoire code>. I.e., P>

Prelude System.Random> import Control.Monad
Prelude System.Random Control.Monad> replicateM 10 randomIO :: IO [Bool]
[True,True,False,True,True,False,False,False,True,True]


2 commentaires

Merci pour votre réponse. En fait, je suis venu avec cette question après avoir lu Lyah où j'ai trouvé que la première pièce dans presque tous les cas est vrai . (Lorsque j'ai vérifié les premiers milliers de cas, j'ai eu beaucoup plus de vrai que faux ) hm ... Même si "Fermer" GRAINES Générez "Similaire", je suis toujours Sentez-vous qu'il est étrange que true apparaît pour 50 milliers de numéros de suite ...


Le problème est que ces ~ 50000 générateurs ensemencés de 1 à 50000 sont suffisamment similaires de telle sorte que le premier élément qu'ils produisent soit vrai . Essayez aléatoire (mkstdgen 100000) :: (bool, stdgen) Pour observer un générateur qui produit initialement un faux . La clé est que vous ne devriez vraiment que graines un générateur unique, plutôt que de semer un tas de générateurs avec des valeurs similaires. Utilisez toutes les semences que vous souhaitez, mais utilisez ensuite les «générateurs générés» pour produire des valeurs aléatoires supplémentaires.



3
votes

Les ordinateurs sont déterministes et ne peuvent pas générer de nombres aléatoires. Ils s'appuient plutôt sur des formules mathématiques qui renvoient une distribution de nombres qui semblent aléatoires. Ceux-ci sont appelés générateurs de nombres pseudo-aléatoires. Cependant, en raison du déterminisme, nous avons le problème que si nous avons rencontré ces formules de la même manière lors de chaque invocation de notre programme, nous obtiendrions les mêmes générateurs de nombres aléatoires. Évidemment, ce n'est pas bon, puisque nous voulons que nos chiffres soient aléatoires! Ainsi, nous devons fournir au générateur aléatoire une valeur de graines initiale qui passe de la course à l'exécution. Pour la plupart des gens (c'est-à-dire ceux qui ne font pas de choses cryptographiques), le générateur de nombres aléatoires est ensemencé par l'heure actuelle. À Haskell, ce générateur pseudo-aléatoire est représenté par le type stdgen code>. La fonction mkstdgen code> est utilisée pour créer un générateur de nombres aléatoires avec une graine. Contrairement à C, où il y a un générateur de nombres aléatoires global, dans Haskell, vous pouvez en avoir autant que vous le souhaitez, et vous pouvez les créer avec différentes graines.

Cependant, il y a une mise en garde: car les chiffres sont pseudo-aléatoires. , rien ne garantit que les générateurs de nombres aléatoires créés avec des nombres de retour de semences différentes qui semblent aléatoires par rapport à l'autre. Cela signifie que lorsque vous appelez randombool code> et donnez-lui des valeurs de semences successives, rien ne garantit que le numéro que vous recevez du stdgen code> que vous créez est aléatoire par rapport au Stdgen code> ensemencé avec son successeur. C'est pourquoi vous obtenez presque 50000 true code>'s. P>

Pour obtenir des données qui ont l'air aléatoire, vous devez continuer à utiliser le même générateur de nombres aléatoires. Si vous remarquez, la fonction aléatoire code> haskell a un type stdgen -> (a, stdgen) code>. Parce que Haskell est pur, la fonction aléatoire code> prend un générateur de nombres aléatoires génère une valeur pseudo-aléatoire (premier élément de la valeur de retour), puis renvoie un nouveau stdgen code> qui Représente le générateur ensemencé avec la graine d'origine, mais prêt à donner un nouveau nombre aléatoire. Vous devez conserver cet autre stdgen code> autour de et transmettez-le à la fonction suivante fonction aléatoire code> afin d'obtenir des données aléatoires. P>

Voici un exemple, générant trois bools aléatoires, a code>, b code> et c code>. p> xxx pré>

remarquez comment le Gen Code> La variable est "fileté" à travers les appels sur aléatoire. P>

Vous pouvez simplifier l'état de passage en utilisant une monade d'état. Par exemple, P>

randomBoolList :: StdGen -> Int -> ([Bool], StdGen)
randomBoolList gen length = runState (replicateM length myRandom) gen


1 commentaires

Strictement, les ordinateurs peuvent produisent des nombres aléatoires si vous avez une source matérielle appropriée. Les derniers processeurs Intel ont même ajouté une instruction de code de machine à cette fin ... (oui, cela n'est que tangentiellement lié au point que vous essayiez de faire.)