问题描述
我正在尝试使用Int.random()
函数使用Swift 4.2+生成种子随机数,但是没有给定的实现允许对随机数生成器进行种子植入.据我所知,唯一的方法是创建一个符合RandomNumberGenerator
协议的新随机数生成器.有没有人建议采用更好的方法,或者是否有符合RandomNumberGenerator的类且具有播种功能的实现,以及如何实现?
I'm trying to generate seeded random numbers with Swift 4.2+, with the Int.random()
function, however there is no given implementation that allows for the random number generator to be seeded. As far as I can tell, the only way to do this is to create a new random number generator that conforms to the RandomNumberGenerator
protocol. Does anyone have a recommendation for a better way to do it, or an implementation of a RandomNumberGenerator conforming class that has the functionality of being seeded, and how to implement it?
此外,我在寻找解决方案的过程中见过两次提到srand
和drand
的函数,但是从很少提及它的角度来看,我不确定使用它是否不好约定,我也找不到关于它们的任何文档.
Also, I have seen two functions srand
and drand
mentioned a couple times while I was looking for a solution to this, but judging by how rarely it was mentioned, I'm not sure if using it is bad convention, and I also can't find any documentation on them.
我正在寻找最简单的解决方案,不一定是最安全或性能最快的解决方案(例如,使用外部库并不理想).
I'm looking for the simplest solution, not necessarily the most secure or fastest performance one (e.g. using an external library would not be ideal).
更新:播种"是指我将种子传递给随机数生成器,以便如果我将同一种子传递给两个不同的设备或在两个不同的时间传递,生成器将产生相同的数字.目的是我为应用程序随机生成数据,而不是将所有数据保存到数据库中,而是想保存种子,并在每次用户加载应用程序时使用该种子重新生成数据.
Update: By "seeded", I mean that I was to pass in a seed to the random number generator so that if I pass in the same seed to two different devices or at two different times, the generator will produce the same numbers. The purpose is that I'm randomly generating data for an app, and rather than save all that data to a database, I want to save the seed and regenerate the data with that seed every time the user loads the app.
推荐答案
因此,我根据Martin R的建议使用了GamePlayKit
的GKMersenneTwisterRandomSource
来创建一个符合RandomNumberGenerator协议的类,我可以使用该类in函数的实例,例如Int.random()
:
So I used Martin R's suggestion to use GamePlayKit
's GKMersenneTwisterRandomSource
to make a class that conformed to the RandomNumberGenerator protocol, which I was able to use an instance of in functions like Int.random()
:
import GameplayKit
class SeededGenerator: RandomNumberGenerator {
let seed: UInt64
private let generator: GKMersenneTwisterRandomSource
convenience init() {
self.init(seed: 0)
}
init(seed: UInt64) {
self.seed = seed
generator = GKMersenneTwisterRandomSource(seed: seed)
}
func next<T>(upperBound: T) -> T where T : FixedWidthInteger, T : UnsignedInteger {
return T(abs(generator.nextInt(upperBound: Int(upperBound))))
}
func next<T>() -> T where T : FixedWidthInteger, T : UnsignedInteger {
return T(abs(generator.nextInt()))
}
}
用法:
// Make a random seed and store in a database
let seed = UInt64.random(in: UInt64.min ... UInt64.max)
var generator = Generator(seed: seed)
// Or if you just need the seeding ability for testing,
// var generator = Generator()
// uses a default seed of 0
let chars = ['a','b','c','d','e','f']
let randomChar = chars.randomElement(using: &generator)
let randomInt = Int.random(in: 0 ..< 1000, using: &generator)
// etc.
通过结合GKMersenneTwisterRandomSource
的种子功能和标准库的随机函数的简单性(例如对于数组的.randomElement()
和对于Int,Bool,Double,等)
This gave me the flexibility and easy implementation that I needed by combining the seeding functionality of GKMersenneTwisterRandomSource
and the simplicity of the standard library's random functions (like .randomElement()
for arrays and .random()
for Int, Bool, Double, etc.)
这篇关于Swift 4.2+播种随机数生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!