web-dev-qa-db-fra.com

Swift 4.2+ Semenant un générateur de nombres aléatoires

J'essaie de générer des nombres aléatoires ensemencés avec Swift 4.2+, avec la fonction Int.random(), mais il n'y a pas de mise en oeuvre donnée permettant au générateur de nombres aléatoires d'être ensemencée . Pour autant que je sache, la seule façon de le faire est de créer un nouveau générateur de nombres aléatoires conforme au protocole RandomNumberGenerator. Est-ce que quelqu'un a une recommandation pour une meilleure façon de le faire, ou une mise en œuvre d'une classe conforme au randomnumbergenerator qui a la fonctionnalité d'être ensemencée et comment la mettre en œuvre?

En outre, j'ai vu deux fonctions srand _ et drand _ _ _ _ _ _ mentionné à quelques reprises alors que je cherchais une solution à cela, mais à en juger par la manière dont il a été rarement mentionné, je ne suis pas sûr de l'utiliser C'est une mauvaise convention et je ne trouve pas non plus de documentation sur eux.

Je cherche la solution la plus simple, pas nécessairement la performance la plus sécurisée ou la plus rapide (par ex. À l'aide d'une bibliothèque externe ne serait pas idéale).

Mise à jour : par "Semeded", je veux dire que je devais passer une graine au générateur de nombres aléatoires de sorte que si je passe dans la même graine à deux dispositifs différents ou à deux heures différentes, le générateur produira les mêmes chiffres. Le but est que je produisais des données au hasard pour une application, et plutôt que d'enregistrer toutes ces données à une base de données, je souhaite enregistrer la graine et régénérer les données avec cette graine chaque fois que l'utilisateur charge l'application.

12
RPatel99

On dirait que la mise en œuvre de Swift de RandomNumberGenerator.next(using:)modifiée en 2019 . Cela affecte Collection.randomElement(using:) et la fait de retourner toujours le premier élément si la mise en œuvre next()->UInt64 _ _ _ La mise en œuvre ne produit pas de valeur uniformément sur le domaine de UInt64. La solution GKRandom fourni ici est donc problématique car elle est next->Int méthode états:

     * The value is in the range of [INT32_MIN, INT32_MAX].

Voici une solution qui fonctionne pour moi en utilisant le RNG dans Swift ''s TensorFlow Trouvé ICI :


public struct ARC4RandomNumberGenerator: RandomNumberGenerator {
  var state: [UInt8] = Array(0...255)
  var iPos: UInt8 = 0
  var jPos: UInt8 = 0

  /// Initialize ARC4RandomNumberGenerator using an array of UInt8. The array
  /// must have length between 1 and 256 inclusive.
  public init(seed: [UInt8]) {
    precondition(seed.count > 0, "Length of seed must be positive")
    precondition(seed.count <= 256, "Length of seed must be at most 256")
    var j: UInt8 = 0
    for i: UInt8 in 0...255 {
      j &+= S(i) &+ seed[Int(i) % seed.count]
      swapAt(i, j)
    }
  }

  // Produce the next random UInt64 from the stream, and advance the internal
  // state.
  public mutating func next() -> UInt64 {
    var result: UInt64 = 0
    for _ in 0..<UInt64.bitWidth / UInt8.bitWidth {
      result <<= UInt8.bitWidth
      result += UInt64(nextByte())
    }
    print(result)
    return result
  }

  // Helper to access the state.
  private func S(_ index: UInt8) -> UInt8 {
    return state[Int(index)]
  }

  // Helper to swap elements of the state.
  private mutating func swapAt(_ i: UInt8, _ j: UInt8) {
    state.swapAt(Int(i), Int(j))
  }

  // Generates the next byte in the keystream.
  private mutating func nextByte() -> UInt8 {
    iPos &+= 1
    jPos &+= S(iPos)
    swapAt(iPos, jPos)
    return S(S(iPos) &+ S(jPos))
  }
}

Conseil de chapeau à mes collègues Samuel, Noé et Stephen qui m'a aidé à aller au fond de cela.

0
Clay Garrett