2016-03-20 1 views
0

J'apprenais la génération de nombres aléatoires avec swift et Gameplaykit. Dans le code suivant, les nombres sont-ils générés quand j'initialise randomDist et donne simplement un échantillon des nombres déjà générés quand j'appelle nextInt ou est-ce que le générateur aléatoire est paresseux quand j'appelle nextInt()?Génération de nombre aléatoire avec GameplayKit

let rand = GKMersenneTwisterRandomSource()   // the generator can be specified 
let randomDist = GKRandomDistribution(randomSource: rand, lowestValue: 50, highestValue: 100) 
randomDist.nextInt() 

Répondre

2

Rappelez-vous qu'un GKRandomDistribution peut utiliser toute sous-jacente randomizer - qui est, non seulement l'une des classes de GameplayKit GKRandomSource, mais toute classe qui implémente le protocole GKRandom. Vous pouvez donc répondre à cette question en implémentant votre propre source aléatoire et en voyant comment/quand ses méthodes sont appelées.

class LoggingRandomSource: GKRandom { 
    let source = GKARC4RandomSource() 
    @objc func nextInt() -> Int { 
     let num = source.nextInt() 
     print("nextInt: \(num)") 
     return num 
    } 
    @objc func nextIntWithUpperBound(upperBound: Int) -> Int { 
     let num = source.nextIntWithUpperBound(upperBound) 
     print("nextIntWithUpperBound: \(num)") 
     return num 
    } 
    @objc func nextUniform() -> Float { 
     let num = source.nextUniform() 
     print("nextUniform: \(num)") 
     return num 
    } 
    @objc func nextBool() -> Bool { 
     let flip = source.nextBool() 
     print("nextBool: \(flip)") 
     return flip 
    } 
} 

let rand = LoggingRandomSource() 
let randomDist = GKRandomDistribution(randomSource: rand, lowestValue: 50, highestValue: 100) 
randomDist.nextInt() 

continuer à explorer avec cette astuce, vous remarquerez quelques petites choses sur les classes de distribution au hasard:

  • GKRandomDistribution appels nextIntWithUpperBound la source aléatoire sous-jacente une fois pour chaque appel à l'une de ses méthodes. Cela est logique, car la source sous-jacente nextIntWithUpperBound est supposée être uniforme, donc tout ce que GKRandomDistribution doit faire est de mapper cet entier uniforme à sa plage lowestValue - highestValue.

  • GKGaussianDistribution effectue deux appels au sous-jacente nextUniform pour chaque appel à l'une de ses méthodes. C'est parce qu'il y a beaucoup de façons de générer une valeur aléatoire gaussienne (alias normal) donnée par deux valeurs aléatoires uniformes - voir le Box-Muller transform.

  • GKShuffledDistributionnextIntWithUpperBound la première fois que vous lui demandez un numéro, mais vous pouvez le demander pour beaucoup plus sans qu'il appelle à nouveau la source sous-jacente. Cela correspond au comportement documenté de cette distribution: elle veille à épuiser toutes les valeurs possibles dans sa plage avant de répéter la même chose. Un moyen facile de le faire est de prendre toutes ces valeurs, de mélanger leur ordre, puis d'extraire une valeur du pool mélangé à chaque appel jusqu'à ce qu'il se vide.