在 Swift 中为给定范围内的 RN 实现 PRNG xoshiro256+?



基于c:这里写的源代码。

我正在尝试在 Swift 中实现 xoshiro256+ 伪随机数生成器 (PRNG(。我需要达到一个点,即算法给我一个介于 0 和 1 之间的数字,然后我可以将其乘以给定范围的计数,然后移位该范围内的第一个数字。

到目前为止,我已经重写了此处源代码中列出的内容:

func rotl(_ x: UInt64, _ k: Int) -> UInt64 {
return (x << k) | (x >> (64 - k))
} // This is the rotating function.
var s: [UInt64] = [1,2,3,4] // I gave a seed vector of the basic 1234.
func next() -> UInt64 {
let result_plus = s[0] + s[3]
let t = s[1] << 17
s[2] ^= s[0]
s[3] ^= s[1]
s[1] ^= s[2]
s[0] ^= s[3]
s[2] ^= t
s[3] = rotl(s[3], 45)
return result_plus
} // This returns the next number in the algorithm while XORing the seed vectors for use in the next call.

但是在调用"下一个"函数 6 次后,我收到一个错误,我猜这是超过 UInt64 的最大限制。这只是一个猜测。

从这一点开始,我将如何继续实现我所追求的目标?我猜我需要丢弃较低的位才能继续调用"下一个"函数而不会超过 UInt64,然后我需要以某种方式转换为双精度?在这一点上,我实际上迷失了。

XOR 无法溢出,因此您的问题出在添加上。 将let result_plus = s[0] + s[3]更改为let result_plus = s[0] &+ s[3](注意"&"(,告诉 Swift 您希望添加在溢出时截断。 您可以阅读Apple的"The Swift Programming Language"一书中有关"溢出运算符"的部分以获取更多详细信息。

要转换为Double请使用:

Double(next() >> 12) / 0x10000000000000

Double有 52 个尾数位,十六进制值为 2**52。这将使用UInt64的前 52 位来生成 [0,1.0( 范围内具有最高可实现精度的结果。

最新更新