我试图用Swift 4.2+生成种子随机数,使用Int.random()
函数,但是没有给定的实现允许随机数生成器被种子化。据我所知,唯一的方法是创建一个符合RandomNumberGenerator
协议的新随机数生成器。有没有人有一个更好的方法来做这件事的建议,或者一个具有种子功能的RandomNumberGenerator符合类的实现,以及如何实现它?
另外,在我寻找解决方案时,我看到两个函数srand
和drand
被提到过几次,但从它被提到的次数来看,我不确定使用它是否是一个糟糕的约定,而且我也找不到关于它们的任何文档。
我正在寻找最简单的解决方案,不一定是最安全或最快的性能(例如,使用外部库将不是理想的)。
**更新:**通过“种子”,我的意思是我将种子传递给随机数生成器,这样如果我将同一种子传递给两个不同的设备或在两个不同的时间,生成器将产生相同的数字。这样做的目的是随机生成应用程序的数据,而不是将所有数据保存到数据库中,我希望保存种子,并在用户每次加载应用程序时使用该种子重新生成数据。
6条答案
按热度按时间vltsax251#
所以我使用Martin R的建议,使用
GamePlayKit
的GKMersenneTwisterRandomSource
来创建一个符合RandomNumberGenerator协议的类,我可以在Int.random()
这样的函数中使用它的示例:使用方法:
通过结合
GKMersenneTwisterRandomSource
的种子功能和标准库的随机函数的简单性(如.randomElement()
用于数组,.random()
用于Int、Bool、Double等),这给了我所需的灵活性和简单实现。vmpqdwk32#
以下是RPatel99的答案的替代方案,它考虑了GKRandom值的范围。
vm0i2vca3#
Swift 5的简化版本:
然后使用它:
fquxozlt4#
Swift的
RandomNumberGenerator.next(using:)
changed in 2019实现这会影响Collection.randomElement(using:)
,并导致它总是返回第一个元素,如果您的生成器的next()->UInt64
实现没有在UInt64
域中均匀地生成值。因此,这里提供的GKRandom
解决方案是有问题的,因为它的next->Int
方法声明:这里有一个解决方案,我在Swift的
TensorFlow
中使用RNG找到了here:感谢我的同事塞缪尔、诺亚和斯蒂芬,他们帮助我弄清了这件事。
cczfrluj5#
我最终使用
srand48()
和drand48()
来生成一个伪随机数,并为特定的测试提供一个种子。因此,在生产环境中,实现使用
SystemRandomNumberGenerator
,但在测试套件中,它使用SeededRandomNumberGenerator
。示例:
eyh26e7m6#
当我尝试使用
Bool.random(using:)
时,srand48
实现对我不起作用。他们制作了:然而,在Swift论坛中,我发现了一个来自Nate Cook的post,它具有一个公共领域算法的Swift实现,在我上面的测试中看起来更随机(不存在明显的模式)