rand64 包提供伪随机数生成器,生成 [0, 2 64 ) 范围内的无符号 64 位数字。
以下伪随机数生成器的实现在其自己的包中提供:
这些生成器实现了 rand.Source64,因此它们可以用作 rand.Rand 的源(从 Go 1.8 开始)。
请注意,某些算法使用 Go 1.9 中的位包。
PRNG 的创建如下所示:
// create a source with the xoshiro256**
source := &xoshiro.Rng256SS{}
// use it as a source in rand.New
rng := rand.New(&source)
// Seed it from a single int64 (negative values are accepted)
rng.Seed(int64Seed)
这是 Java 8 的 SplittableRandom 生成器的固定增量版本。另请参阅快速可分割伪随机数生成器页面。
Go 实现基于 Sebastiano Vigna 的 C 参考实现。
期间 2 256 -1
根据算法作者的说法:
xoshiro256**(XOR/移位/旋转)是我们万能的、坚如磐石的生成器(但不是加密安全的生成器)。它具有出色的(亚纳秒)速度,对于任何并行应用程序来说都足够大的状态空间(256 位),并且它通过了我们所知的所有测试。
然而,如果只需生成 64 位浮点数(通过提取高 53 位),xoshiro256+ 是一种速度稍快(约 15%)的生成器,具有类似的统计特性。对于一般用途,必须考虑其最低位具有较低的线性复杂度,并且将无法通过线性测试;然而,低线性复杂度在实践中几乎不会产生任何影响,并且如果您使用高位生成浮点数(我们计算了最低位线性复杂度的精确估计),则肯定不会产生任何影响。
期间 2 128 -1
根据算法作者的说法:
xoroshiro128** (XOR/旋转/移位/旋转) 和 xoroshiro128+ 与 xoshiro256 具有相同的速度并使用一半的空间;同样的评论也适用。它们仅适用于低规模并行应用;此外,xoroshiro128+ 对汉明权重表现出轻微的依赖性,在我们的测试中输出 5 TB 后会出现故障。我们相信这种轻微的偏差不会影响任何应用程序。
Go 实现基于 David Blackman 和 Sebastiano Vigna 的 C 参考实现。
欲了解更多信息,请访问 xoshiro / xoroshiro 生成器和 PRNG 竞赛页面。
期间 2 128
这是一个排列同余生成器,定义为
PCG:一系列简单、快速、节省空间、统计良好的随机数生成算法
梅丽莎·E·奥尼尔,哈维穆德学院
https://www.cs.hmc.edu/tr/hmc-cs-2014-0905.pdf
虽然PCG
指的是整个算法系列(另请参见 http://pcg-random.org),但唯一提供的算法是 PCG XSL RR 128/64 LCG。
Go 实现基于 Melissa O'Neill 和 PCG 项目贡献者的 C 参考实现。
第二期19937 -1
这是基于 Makoto Matsumoto 和 Takuji Nishimura 的 mt19937-64.c C 实现的纯 Go 实现。
有关 Mersenne Twister 算法和其他实现的更多信息,请访问 http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
请注意,此算法仅适用于需要与使用相同算法的其他应用程序进行互操作的应用程序。由于已知它无法通过简单的统计测试,并且在 amd64 上速度最慢,因此不建议将其用于任何其他目的。
不是真正的 PRNG。
IoRand 包是一个简单的包装器,用于通过 io.Reader 读取字节流。它可以用作 crypto/rand 的包装器来为 math/rand 包构建 rand.Source64 :
package main
import (
"bufio"
crand "crypto/rand"
"encoding/binary"
"math/rand"
"github.com/db47h/rand64/v3/iorand"
)
// Wrap crypto/rand in an IoRand
func main () {
// first, wrap crypto/rand.Reader in a buffered bufio.Reader
bufferedReader := bufio . NewReader ( crand . Reader )
// Create the new IoRand Source
ior := iorand . New ( bufferedReader , binary . LittleEndian )
// use it as rand.Source64
rng := rand . New ( ior )
// get random numbers...
for i := 0 ; i < 4 ; i ++ {
_ = rng . Uint64 ()
}
}
这些基准测试是使用 go 1.12.5 完成的。
算法 | AMD FX-6300 | 酷睿i5 6200U | ARM Cortex-A7 @900MHz |
---|---|---|---|
xoshiro256** | 5.53 纳秒/操作 | 106.0 纳秒/操作 | |
小四郎256+ | 5.48 纳秒/操作 | 86.1 纳秒/操作 | |
克罗四郎128** | 5.16 纳秒/操作 | 79.2 纳秒/操作 | |
异色四郎128+ | 5.15 纳秒/操作 | 62.7 纳秒/操作 | |
PCG XSL RR 128/64 LCG | 5.29 纳秒/操作 | 254.0 纳秒/操作 | |
分割混合64 | 4.30 纳秒/操作 | 77.5 纳秒/操作 | |
梅森龙卷风 19937 | 8.82 纳秒/操作 | 136.0 纳秒/操作 | |
数学/兰德 | 7.01 纳秒/操作 | 68.4 纳秒/操作 |
请注意,与早期版本相比,基准测试显示性能较慢。这是因为我们直接调用了 Rng.Uint64,而不是通过 rand.Rand64 接口。为了与 Go 标准库的 rng 进行公平比较,所有基准测试现在都通过 rand.Source64 接口。
远离 splitmix64 和令人尊敬的 Mersenne-Twister 19937。
人们对 Go 的 math/rand 知之甚少(请参阅此处、此处),并且有人建议用 PCG 生成器替换它。
所提供的 PCG、xoshiro256** 和 xoroshiro128** 据称可通过所有已知测试;根据各自的作者。不过,请注意该特定 PCG 算法在 32 位平台上的较差性能(同时影响 ARM 和 x86)。
rand64 支持 go 模块。以前的版本 1.x 和 2.x 已移至各自的分支。由于没有 go.mod 的 semver 标签似乎扰乱了 go 模块,因此这些版本的标签已被重置。
该软件包是根据 ISC 许可证条款发布的(请参阅存储库根目录下的 LICENSE 文件)。此外,以下算法的使用受附加许可证的约束: